📄 homopuls.c
字号:
/*
* 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 (c) 1994-96 by The MathWorks, Inc.
* All Rights Reserved
* $Revision: 1.1 $ $Date: 1996/04/01 19:02:56 $
*/
#define S_FUNCTION_NAME homopuls
#ifdef MATLAB_MEX_FILE
#include <stdio.h> /* needed for declaration of sprintf */
#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"
/*
* 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 void mdlInitializeSizes (S)
SimStruct *S;
{
/*
* Set-up size information.
*/
if (ssGetNumArgs(S) == NUM_ARGS) {
int 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);
ssSetNumContStates( S, 0);
ssSetNumDiscStates( S, 0);
ssSetNumInputs( S, 0);
ssSetNumOutputs( S, dividerSize);
ssSetDirectFeedThrough(S, 0);
ssSetNumInputArgs( S, NUM_ARGS);
ssSetNumSampleTimes( S, dividerSize);
ssSetNumRWork( S, 4*dividerSize+2); /* store the timing */
ssSetNumIWork( S, dividerSize); /* store the last time access. */
ssSetNumPWork( S, 0);
} else {
#ifdef MATLAB_MEX_FILE
char err_msg[256];
sprintf(err_msg, "Wrong number of input arguments passed to S-function MEX-file.\n %d input arguments were passed in when expecting %d input arguments.\n", ssGetNumArgs(S) + 4, NUM_ARGS + 4);
mexErrMsgTxt(err_msg);
#endif
}
}
/*
* mdlInitializeSampleTimes - initializes the array of sample times stored in
* the SimStruct associated with this S-Function.
*/
static void mdlInitializeSampleTimes(S)
SimStruct *S;
{
double sampleTime, offsetTime, tmp;
int i, dividerSize, adj;
int *reverse = ssGetIWork(S);
sampleTime = mxGetPr(SAMPLE_TIME)[0];
dividerSize = mxGetN(DIVIDER_EACH) * mxGetM(DIVIDER_EACH);
for (i=0; i < dividerSize; i++) {
offsetTime = mxGetPr(OFFSET_EACH)[i];
tmp = sampleTime/2./mxGetPr(DIVIDER_EACH)[i];
ssSetSampleTimeEvent(S, i, tmp);
adj = (int)(offsetTime / tmp);
tmp = offsetTime - ((double)adj) * tmp;
ssSetOffsetTimeEvent(S, i, tmp);
/*
if (tmp != offsetTime - ((double)((int)(offsetTime/tmp/2))) * tmp *2) {
reverse[i] = 1;
} else {
reverse[i] = 0;
}
*/
}
}
/*
* mdlInitializeConditions - initializes the states for the S-Function
*/
static void mdlInitializeConditions(x0, S)
double *x0;
SimStruct *S;
{
int dividerSize = mxGetN(DIVIDER_EACH) * mxGetM(DIVIDER_EACH);
double *hit_base = ssGetRWork(S);
double *next_hit = ssGetRWork(S) + 1;
double *last_value = ssGetRWork(S) + dividerSize + 1;
double *increment = ssGetRWork(S) + dividerSize * 2 + 1;
double *adj_offset = ssGetRWork(S) + dividerSize * 3 + 1;
double *tolerance = ssGetRWork(S) + dividerSize * 4 + 1;
int *reverse = ssGetIWork(S);
double sampleTime, offsetTime, offsetMin, tmp, tol;
int i, adj;
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)(offsetTime / tmp);
tmp = offsetTime - ((double)adj) * tmp;
if (tmp != offsetTime - ((double)((int)(offsetTime/tmp/2))) * tmp *2) {
reverse[i] = 1;
} else {
reverse[i] = 0;
}
#ifdef MATLAB_MEX_FILE
if (0) {
char err_msg[255];
sprintf(err_msg, "reverse[%d]=%d; ", 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 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(y, x, u, S, tid)
double *y, *x, *u;
SimStruct *S;
int tid;
{
int dividerSize = mxGetN(DIVIDER_EACH) * mxGetM(DIVIDER_EACH);
double *hit_base = ssGetRWork(S);
double *next_hit = ssGetRWork(S) + 1;
double *last_value = ssGetRWork(S) + dividerSize + 1;
double *increment = ssGetRWork(S) + dividerSize * 2 + 1;
double *adj_offset = ssGetRWork(S) + dividerSize * 3 + 1;
double *tolerance = ssGetRWork(S) + dividerSize * 4 + 1;
int *reverse = ssGetIWork(S);
double time_clock, tol;
int i;
tol = *tolerance;
time_clock = ssGetT(S) + tol;
for (i = 0; i < dividerSize; i++) {
if (time_clock >= next_hit[i]) {
int num;
double sampleTime;
sampleTime = mxGetPr(SAMPLE_TIME)[0];
num = (int)((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 err_msg[255];
sprintf(err_msg, "reverse[%d]=%d; last_value=%d; ", i, reverse[i], (int)last_value[i]);
mexPrintf(err_msg);
}
#endif
if (reverse[i])
last_value[i] = ((int)last_value[i] + 1) % 2;
#ifdef MATLAB_MEX_FILE
if (0) {
char err_msg[255];
sprintf(err_msg, "new_last_value=%d;\n ", (int)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){
double 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(x, u, S, tid)
double *x, *u;
SimStruct *S;
int tid;
{
}
/*
* mdlDerivatives - computes the derivatives of the S-Function
*/
static void mdlDerivatives(dx, x, u, S, tid)
double *dx, *x, *u;
SimStruct *S;
int tid;
{
}
/*
* mdlTerminate - called at termination of model execution.
*/
static void mdlTerminate(S)
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -