/* admultiq3.c - xPC Target, non-inlined S-function driver for: */ /* D/A section of MultiQ3 ISA board (Quanser) */ /* Written by R.A. de Callafon, Feb. 2004, Dept. of MAE, UCSD */ /* xPC is Copyright 1996-2002 The MathWorks, Inc. */ #define S_FUNCTION_LEVEL 2 #undef S_FUNCTION_NAME #define S_FUNCTION_NAME damultiq3 #include #include #include "simstruc.h" #ifdef MATLAB_MEX_FILE #include "mex.h" #else #include #include "io_xpcimport.h" #endif /* Input Arguments */ #define NUM_PARAMS (3) #define BASE_ADDRESS_ARG (ssGetSFcnParam(S,0)) #define CHANNEL_ARG (ssGetSFcnParam(S,1)) #define SAMPLE_TIME_PARAM (ssGetSFcnParam(S,2)) /* Convert S Function Parameters to Variables of Unsigned Integer Type */ #define BASE ((uint_T) mxGetPr(BASE_ADDRESS_ARG)[0]) #define SAMPLE_TIME ((real_T) mxGetPr(SAMPLE_TIME_PARAM)[0]) #define SAMPLE_OFFSET ((real_T) mxGetPr(SAMPLE_TIME_PARAM)[1]) /* Definition of Quanser Register Adresses for DA conversion */ #define DA_DATA (BASE + 0x02) /* a 16 bit write (only lowest 12 bits matter) is the data for DA conversion */ #define CONTROL_REG (BASE + 0x06) /* the address of the CONTROL REGISTER */ #define STATUS_REG (BASE + 0x06) /* the address of the CONTROL REGISTER (or better STATUS REGISTER in case of reading) */ /* Definition of 16 bit CONTROL REGISTER values for the Quanser card */ #define AD_SH 0x200 /* (S/H) = disable sample and hold on the A/D (keep this 1 all the time) */ #define LATCH_ON 0x1800 /* LD0 and LD1 on the CONTROL REGISTER to be latched before DA conversion */ #define AD_CLOCK_4M 0x400 /* (CLK) = choose clock frequency of the A/D, (1 = 4MHz, 0 = 2 MHz) */ #define CONTROL_MUST (AD_SH | AD_CLOCK_4M) /* bit wise OR, so we keep both S/H and CLK high all the time */ /* Definition of msg string in case we need to report errors */ static char_T msg[256]; #ifndef MATLAB_MEX_FILE static void DAOutput(SimStruct *S, uint_T channel, real_T value) { real_T out; /* convert the real valued data (between -5 and 5) to a 12 bit integer value */ out=4095*(value+5)/10; if (out<0) out=0; if (out>4096) out=4096; /* channel number to DA0 DA1 DA2 and latch with LD0 LD1 both high */ /* also keep S/H and AD_CLOCK_4M high (CONTROL_MUST) */ /* and write all these values to the control register */ rl32eOutpW(CONTROL_REG, (CONTROL_MUST | LATCH_ON | channel)); /* write the actual integer data (in 12 bits) to the DA_DATA register */ rl32eOutpW(DA_DATA,(uint_T)out); /* release the latch by setting LD0 and LD1 back to low */ /* which can be done by resetting the CONTROL_REGISTER */ rl32eOutpW(CONTROL_REG, CONTROL_MUST); } #endif /*====================* * S-function methods * *====================*/ static void mdlCheckParameters(SimStruct *S) { } static void mdlInitializeSizes(SimStruct *S) { uint_T i; #ifndef MATLAB_MEX_FILE #include "io_xpcimport.c" #endif ssSetNumSFcnParams(S, NUM_PARAMS); if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) { mdlCheckParameters(S); if (ssGetErrorStatus(S) != NULL) { return; } } else { return; /* Parameter mismatch will be reported by Simulink */ } ssSetNumContStates(S, 0); ssSetNumDiscStates(S, 0); if (!ssSetNumInputPorts(S, (mxGetNumberOfElements(CHANNEL_ARG)))) return; for (i=0;i