regdown.c
上传用户:loeagle
上传日期:2013-03-02
资源大小:1236k
文件大小:10k
源码类别:

通讯编程文档

开发平台:

Matlab

  1. /* $Revision: 1.21 $ */
  2. /*
  3.  * REGDOWN   A Simulink register down block
  4.  *
  5.  * Syntax:  [sys, x0] = regdown(t, x, u, flag, OutputIndex, Increament, trigThreshold, cycl_flag)
  6.  *      This block outputs a vector with the initial index given in OutputIndex.
  7.  *      The increament of the index is given in Increament. This block has three
  8.  *      input veriables. The first is a vector providing the register signals.
  9.  *      The second is a clock signal to trigger the refreshment of the register in
  10.  *      in this block. The third is a trigger signal for the output refreshment.
  11.  *      The block uses the rising edge of both second and third input pulse
  12.  *      to trigger the action. At the rising edge of the third signal, a positive
  13.  *      signal at the third inport would cause the output refreshemnt.
  14.  *
  15.  * Wes Wang 8/23, 1994
  16.  *
  17.  * Copyright 1996-2001 The MathWorks, Inc.
  18.  */
  19. #define S_FUNCTION_NAME regdown
  20. #ifdef MATLAB_MEX_FILE
  21. #include "mex.h"      /* needed for declaration of mexErrMsgTxt */
  22. #endif
  23. /*
  24.  * need to include simstruc.h for the definition of the SimStruct and
  25.  * its associated macro definitions.
  26.  */
  27. #include "simstruc.h"
  28. #include "tmwtypes.h"
  29. /*
  30.  * Defines for easy access of the input parameters
  31.  */
  32. #define NUM_ARGS        4
  33. #define OUTPUT_INDEX   ssGetArg(S,0)
  34. #define INCREAMENT     ssGetArg(S,1)
  35. #define TRIG_THRSHLD   ssGetArg(S,2)
  36. #define CYCLIC_FLAG    ssGetArg(S,3)
  37. /*
  38.  * mdlInitializeSizes - called to initialize the sizes array stored in
  39.  *                      the SimStruct.  The sizes array defines the
  40.  *                      characteristics (number of inputs, outputs,
  41.  *                      states, etc.) of the S-Function.
  42.  */
  43. static void mdlInitializeSizes(SimStruct *S)
  44. {
  45.   int_T num_output_idx, num_increament;
  46.     
  47.   /*
  48.    * Set-up size information.
  49.    */ 
  50.   if (ssGetNumArgs(S) == NUM_ARGS) {
  51.     /* check the dimension for OUTPUT_INDEX and INCREAMNET */
  52.     num_output_idx = mxGetN(OUTPUT_INDEX) * mxGetM(OUTPUT_INDEX);
  53.     num_increament  = mxGetN(INCREAMENT)   * mxGetM(INCREAMENT);
  54.     if (num_output_idx <= 0) {
  55. #ifdef MATLAB_MEX_FILE
  56.       mexErrMsgTxt("OutputIndex cannot be a empty vector.");
  57. #endif        
  58.     }
  59.     if (num_output_idx != num_increament) {
  60.       if (num_increament != 1) {
  61. #ifdef MATLAB_MEX_FILE
  62.          mexErrMsgTxt("The vector size for OutputIndex and Increment must be the same.");
  63. #endif
  64.       }
  65.     }
  66.     
  67.     if ((mxGetN(TRIG_THRSHLD)*mxGetM(TRIG_THRSHLD) != 1)) {
  68. #ifdef MATLAB_MEX_FILE
  69.       mexErrMsgTxt("The threshold must be a scalar.");
  70. #endif
  71.     } 
  72.        
  73.     ssSetNumContStates(    S, 0);
  74.     ssSetNumDiscStates(    S, 0);
  75.     ssSetNumInputs(        S, -1);
  76.     ssSetNumOutputs(       S, 1 + num_output_idx);
  77.     ssSetDirectFeedThrough(S, 1);
  78.     ssSetNumInputArgs(     S, NUM_ARGS);
  79.     ssSetNumSampleTimes(   S, 1);
  80.     ssSetNumRWork(         S, -1);
  81.     /* the buffer size is input_vector + trig_in + trig_out
  82.      * R vector is assigned as buffer, lastTime2, lastTime3
  83.      */
  84.     ssSetNumIWork(         S, 2 + 2 * num_output_idx);
  85.     ssSetNumPWork(         S, 0);
  86.   }  else {
  87. #ifdef MATLAB_MEX_FILE
  88.     char_T err_msg[256];
  89.     sprintf(err_msg, "Wrong number of input arguments passed to S-function MEX-file.n"
  90.         "%d input arguments were passed in when expecting %d input arguments.n", ssGetNumArgs(S) + 4, NUM_ARGS + 4);
  91.     mexErrMsgTxt(err_msg);
  92. #endif 
  93.   }
  94. }    
  95. /*
  96.  * mdlInitializeSampleTimes - initializes the array of sample times stored in
  97.  *                            the SimStruct associated with this S-Function.
  98.  */
  99. static void mdlInitializeSampleTimes(SimStruct *S)
  100. {
  101.      /*
  102.      * Note, blocks that are continuous in nature should have a single
  103.      * sample time of 0.0.
  104.      */
  105.     ssSetSampleTimeEvent(S, 0, INHERITED_SAMPLE_TIME);
  106.     ssSetOffsetTimeEvent(S, 0, FIXED_IN_MINOR_STEP_OFFSET);
  107. }
  108. /*
  109.  * mdlInitializeConditions - initializes the states for the S-Function
  110.  */
  111. static void mdlInitializeConditions(real_T *x0, SimStruct *S)
  112. {
  113.     int_T num_output_idx   = ssGetNumOutputs(S) - 1;
  114.     real_T *regi         = ssGetRWork(S);
  115.     int_T *lastTrig2       = ssGetIWork(S);
  116.     int_T *lastTrig3       = ssGetIWork(S) + 1;
  117.     int_T *outputIndex     = ssGetIWork(S) + 2; 
  118.     int_T *increament      = ssGetIWork(S) + num_output_idx + 2;
  119.     int_T num_increament   = mxGetN(INCREAMENT) * mxGetM(INCREAMENT);
  120.     int_T regiSize         = ssGetNumInputs(S) - 2;
  121.     int_T i;
  122.     /* 
  123.      * Initialize the buffer to all zeros, we could allow this to
  124.      * be an additional paramter.
  125.      */
  126.     
  127.     for (i = 0; i < regiSize; i++)
  128.         *regi++ = 0.;
  129.     /*
  130.      * Initialize the current buffer position, buffer start, and output index
  131.      */
  132.     
  133.     for (i = 0; i < num_output_idx; i++) {
  134.         if (mxGetPr(OUTPUT_INDEX)[i] < 0) {
  135. #ifdef MATLAB_MEX_FILE
  136.              mexErrMsgTxt("Output Index must be positive integers.");
  137. #endif
  138.                 }
  139.         *outputIndex++ = (int_T) mxGetPr(OUTPUT_INDEX)[i];
  140.         if (num_increament == 1) {
  141.             *increament++ = (int_T)mxGetPr(INCREAMENT)[0];
  142.                 } else {
  143.             *increament++ = (int_T)mxGetPr(INCREAMENT)[i];
  144.         }
  145.     }
  146.     *lastTrig2 = 0;
  147.     *lastTrig3 = 0;
  148.     if (regiSize >= 0) {
  149.         real_T *lastTime2    = ssGetRWork(S) + regiSize;
  150.         real_T *lastTime3    = ssGetRWork(S) + regiSize + 1;
  151.         *lastTime2 = -1.0;
  152.         *lastTime3 = -1.0;
  153.     }
  154. }
  155. /*
  156.  * mdlOutputs - computes the outputs of the S-Function
  157.  */
  158. static void mdlOutputs(real_T *y, const real_T *x, const real_T *u, SimStruct *S, int_T tid)
  159. {
  160.     int_T num_output_idx   = ssGetNumOutputs(S) - 1;
  161.     real_T *regi         = ssGetRWork(S);
  162.     real_T  trigThreshold   = mxGetPr(TRIG_THRSHLD)[0];
  163.     
  164.     int_T *lastTrig2       = ssGetIWork(S);
  165.     int_T *lastTrig3       = ssGetIWork(S) + 1;
  166.     int_T *outputIndex     = ssGetIWork(S) + 2; 
  167.     int_T *increament      = ssGetIWork(S)+ num_output_idx + 2;
  168.     int_T regiSize         = ssGetNumInputs(S) - 2;
  169.     real_T *lastTime2    = ssGetRWork(S) + regiSize;
  170.     real_T *lastTime3    = ssGetRWork(S) + regiSize + 1;
  171.     real_T currentTime   = ssGetT(S);
  172.     
  173.     int_T cycl_flag   = (int_T)mxGetPr(CYCLIC_FLAG)[0];
  174.     
  175.     int_T i, modulo_idx;
  176.     if ((u[regiSize] >= trigThreshold) & (*lastTrig2 == 0)) {
  177.       for (i = 0; i < regiSize; i++)
  178.         regi[i] = u[i];
  179.       /* refresh output index */
  180.       for (i = 0; i < num_output_idx; i++)
  181.         outputIndex[i] = (int_T) mxGetPr(OUTPUT_INDEX)[i];
  182.       /* reset trigger flag */
  183.       *lastTrig2 = 1;
  184.       y[num_output_idx] = 1;
  185.       *lastTime2 = currentTime;
  186.     } else {
  187.       if (u[regiSize] >= trigThreshold) {
  188.         if (currentTime > 0) {
  189.           if ((currentTime - *lastTime2) / currentTime < 0.00000001) {
  190.             /* re-refresh the buffer, use the most recent one */
  191.             for (i = 0; i < regiSize; i++)
  192.               regi[i] = u[i];
  193.             /* verify whether the output needs to refresh */
  194.             if ((u[regiSize + 1] >= trigThreshold) && ((currentTime - *lastTime3) / currentTime < 0.00000001)) {
  195.               int_T backIndex;
  196.                 
  197.               for (i = 0; i < num_output_idx; i++) {
  198.                 backIndex = outputIndex[i] - increament[i];
  199.                 if (cycl_flag > 0) {
  200.                   if (backIndex >= 0)
  201.                     backIndex %= regiSize;
  202.                   else 
  203.                     backIndex = (regiSize - ((-backIndex) % regiSize)) % regiSize;
  204.                   y[i] = regi[backIndex];
  205.                 } else {
  206.                   if ((backIndex < regiSize) & (backIndex >= 0))
  207.                     y[i] = regi[backIndex];
  208.                   else
  209.                     y[i] = 0.0;
  210.                 }
  211.               }
  212.             }
  213.           }
  214.         }
  215.       } else if (*lastTrig2 == 1) {
  216.         if (u[regiSize] < trigThreshold) {
  217.           *lastTrig2 = 0;
  218.           y[num_output_idx] = 0.0;
  219.         }
  220.       }
  221.     }
  222.     if ((u[regiSize + 1] >= trigThreshold) & (*lastTrig3 == 0)) {
  223.       for (i = 0; i < num_output_idx; i++) {
  224.         /* refresh output */
  225.         if (cycl_flag > 0) {
  226.           modulo_idx = outputIndex[i];
  227.           if (modulo_idx >= 0)
  228.             modulo_idx %= regiSize;
  229.           else 
  230.             modulo_idx = (regiSize - ((-modulo_idx) % regiSize)) % regiSize;
  231.           y[i] = regi[modulo_idx];
  232.         } else {
  233.           if ((outputIndex[i] < regiSize) & (outputIndex[i] >= 0))
  234.             y[i] = regi[outputIndex[i]];
  235.           else
  236.             y[i] = 0.0;
  237.         }
  238.         /* refresh output index */                
  239.         outputIndex[i] += increament[i];
  240.       }
  241.       *lastTrig3 = 1;
  242.       *lastTime3 = currentTime;
  243.     } else {
  244.       if (*lastTrig3 == 1) {
  245.         if (u[regiSize+1] < trigThreshold)
  246.           *lastTrig3 = 0;
  247.       }
  248.       if (ssGetT(S) <= 0.0) {
  249.         for (i = 0; i < num_output_idx; i++)
  250.           y[i] = 0.0;         
  251.       } 
  252.     }
  253. }
  254. /*
  255.  * mdlUpdate - computes the discrete states of the S-Function
  256.  */
  257. static void mdlUpdate(real_T *x, const real_T *u, SimStruct *S, int_T tid)
  258. {
  259. }
  260. /*
  261.  * mdlDerivatives - computes the derivatives of the S-Function
  262.  */
  263. static void mdlDerivatives(real_T *dx, const real_T *x, const real_T *u, SimStruct *S, int_T tid)
  264. {
  265. }
  266. /*
  267.  * mdlTerminate - called at termination of model execution.
  268.  */
  269. static void mdlTerminate(SimStruct *S)
  270. {
  271. }
  272. #ifdef  MATLAB_MEX_FILE    /* Is this file being compiled as a MEX-file? */
  273. #include "simulink.c"   /* MEX-File interface mechanism */
  274. #else
  275. #include "cg_sfun.h"    /* Code generation registration function */
  276. #endif