diff --git a/adaptors/matlab/Makefile b/adaptors/matlab/Makefile index 393415e9e28c90ed06d40fe9607dbe5b2d9e30dd..561bfd6da50cf58ee9fecd5e3cb29de9a65785bf 100644 --- a/adaptors/matlab/Makefile +++ b/adaptors/matlab/Makefile @@ -1,22 +1,9 @@ LIBRARIES=libmoberg4simulink.so -SFUNC=analogin analogout digitalin digitalout encoderin -MATLAB_VERSION= -MEX=MATLAB_VERSION=$(MATLAB_VERSION) mex -MEX_SUFFIX=$(shell $(MEX) -v -n analogin.c \ - | sed -e 's/^.*LDEXTENSION.*[.]\(mex.*\)/\1/p;d') - -CCFLAGS+=-Wall -Werror -I. -I../.. -g +CCFLAGS+=-Wall -Werror -O3 -I. -I../.. -g all: $(LIBRARIES:%=../../build/%) -.PHONY: SFUNC -SFUNC: $(SFUNC:%=../../build/%.$(MEX_SUFFIX)) - ../../build/libmoberg4simulink.so: moberg4simulink.c Makefile $(CC) -o $@ $(CCFLAGS) -L../../build -shared -fPIC -lmoberg $< ../../build/libmoberg4simulink.so: ../../moberg.h - -../../build/%.$(MEX_SUFFIX): %.c Makefile - $(MEX) CFLAGS="$(CCFLAGS) -fPIC" \ - -outdir ../../build -L../../build -lmoberg4simulink $< diff --git a/adaptors/matlab/Makefile.mex b/adaptors/matlab/Makefile.mex new file mode 100644 index 0000000000000000000000000000000000000000..322bed350e3c0a2a193c886f1085559d82a4a03e --- /dev/null +++ b/adaptors/matlab/Makefile.mex @@ -0,0 +1,26 @@ +MATLAB_VERSION= +MEX=MATLAB_VERSION=$(MATLAB_VERSION) mex +SUFFIX=$(shell $(MEX) -v -n analogin.c 2>&1 | \ + sed -e 's/^.*LDEXTENSION.*[.]\(mex.*\)/\1/p;d') +TARGETS=realtimer \ + analogin analogout \ + digitalin digitalout \ + encoderin + +EXTRAFLAGS_realtimer= +EXTRAFLAGS_analogin=-lmoberg4simulink +EXTRAFLAGS_analogout=-lmoberg4simulink +EXTRAFLAGS_digitalin=-lmoberg4simulink +EXTRAFLAGS_digitalout=-lmoberg4simulink +EXTRAFLAGS_encoderin=-lmoberg4simulink + +all: $(TARGETS:%=%.$(SUFFIX)) + +%.$(SUFFIX): %.c Makefile + $(MEX) CFLAGS='$$CFLAGS -Wall -Werror -I.' $< $(EXTRAFLAGS_$*) + +clean: + rm -f *~ + +realclean: clean + rm -f $(TARGETS:%=%.mex*) diff --git a/adaptors/matlab/realtimer.c b/adaptors/matlab/realtimer.c new file mode 100644 index 0000000000000000000000000000000000000000..2f7b1e82ea5d6ec8781fe15bc428467131197b49 --- /dev/null +++ b/adaptors/matlab/realtimer.c @@ -0,0 +1,137 @@ +/* + realtimer.c, + a MEX file for syncing elapsed Simulink time to elapsed wall time. + + Copyright (C) 1999-2005 Anders Blomdell <anders.blomdell@control.lth.se> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#define S_FUNCTION_LEVEL 2 +#define S_FUNCTION_NAME realtimer + +#include "simstruc.h" +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> +#include <time.h> + +static unsigned long long TIME2ULL(struct timeval t) +{ + unsigned long long result; + result = (unsigned long long)t.tv_sec * 1000000 + t.tv_usec; + return result; +} + +#if 0 +static struct timeval ULL2TIME(unsigned long long t) +{ + struct timeval result; + result.tv_sec = t / 1000000; + result.tv_usec = t % 1000000; + return result; +} +#endif + +static struct timespec ULL2TIMESPEC(unsigned long long t) +{ + struct timespec result; + result.tv_sec = t / 1000000; + result.tv_nsec = (t % 1000000) * 1000; + return result; +} + +static void mdlInitializeSizes(SimStruct *S) +{ + ssSetNumSFcnParams(S, 1); /* Number of expected parameters */ + if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) { return; } + + ssSetNumContStates(S, 0); + ssSetNumDiscStates(S, 0); + + if (!ssSetNumInputPorts(S, 0)) { return; } + + if (!ssSetNumOutputPorts(S, 1)) { return; } + ssSetOutputPortWidth(S, 0, 1); + + ssSetNumSampleTimes(S, 1); + + ssSetNumRWork(S, 0); + ssSetNumIWork(S, 6); /* 0,1: long long h + 2,3: long long t + 4,5: long long diff */ + ssSetNumPWork(S, 0); + ssSetNumModes(S, 0); + + ssSetNumNonsampledZCs(S, 0); + + ssSetOptions(S, 0); +} + +static void mdlInitializeSampleTimes(SimStruct *S) +{ + ssSetSampleTime(S, 0, mxGetScalar(ssGetSFcnParam(S, 0))); + ssSetOffsetTime(S, 0, 0.0); +} + +#define MDL_START +static void mdlStart(SimStruct *S) +{ + struct timeval now; + unsigned long long *work = (unsigned long long *)ssGetIWork(S); + gettimeofday(&now, 0); + work[0] = mxGetScalar(ssGetSFcnParam(S, 0)) * 1000000; + work[1] = TIME2ULL(now); + work[2] = 0; +} + +static void mdlOutputs(SimStruct *S, int_T tid) +{ + unsigned long long *work = (unsigned long long *)ssGetIWork(S); + real_T *y = ssGetOutputPortRealSignal(S,0); + + *y = 1.0 - ((real_T)work[2] / (real_T)work[0]); +} + +#define MDL_UPDATE +static void mdlUpdate(SimStruct *S, int_T tid) +{ + unsigned long long *work = (unsigned long long *)ssGetIWork(S); + long long diff; + struct timeval now; + + work[1] += work[0]; + gettimeofday(&now, 0); + diff = work[1] - TIME2ULL(now); + if ((diff) <= 0) { + diff = 0; + work[1] = TIME2ULL(now); + } else { + struct timespec delay = ULL2TIMESPEC(diff); + nanosleep(&delay, NULL); + } + work[2] = diff; +} + +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 diff --git a/moberg.spec.template b/moberg.spec.template index 3254e98832f2cfd672a9e670db2c6739d61b95a6..36e54381770aed0586f9e451dfbac82797eef6d7 100644 --- a/moberg.spec.template +++ b/moberg.spec.template @@ -58,26 +58,28 @@ mkdir -p ${RPM_BUILD_ROOT}%{_includedir} cp moberg.h ${RPM_BUILD_ROOT}%{_includedir} mkdir -p ${RPM_BUILD_ROOT}/opt/matlab/src/moberg -cp adaptors/matlab/*.h ${RPM_BUILD_ROOT}/opt/matlab/src/moberg -cp adaptors/matlab/*in.c ${RPM_BUILD_ROOT}/opt/matlab/src/moberg -cp adaptors/matlab/*out.c ${RPM_BUILD_ROOT}/opt/matlab/src/moberg -cp adaptors/matlab/Makefile ${RPM_BUILD_ROOT}/opt/matlab/src/moberg +mkdir -p ${RPM_BUILD_ROOT}%{_includedir} +cp adaptors/matlab/moberg4simulink.h ${RPM_BUILD_ROOT}%{_includedir} +cp adaptors/matlab/realtimer.c ${RPM_BUILD_ROOT}/opt/matlab/src/moberg +cp adaptors/matlab/*in.c ${RPM_BUILD_ROOT}/opt/matlab/src/moberg +cp adaptors/matlab/*out.c ${RPM_BUILD_ROOT}/opt/matlab/src/moberg +cp adaptors/matlab/Makefile.mex ${RPM_BUILD_ROOT}/opt/matlab/src/moberg/Makefile %files %defattr(-,root,root,-) -%attr(04755,root,root) %{_libdir}/libmoberg.so -%attr(04755,root,root) %{_libdir}/libmoberg_serial2002.so +%{_libdir}/libmoberg.so +%{_libdir}/libmoberg_serial2002.so %files comedi %defattr(-,root,root,-) -%attr(04755,root,root) %{_libdir}/libmoberg_comedi.so +%{_libdir}/libmoberg_comedi.so %files devel %defattr(-,root,root,-) -%attr(04755,root,root) %{_includedir}/moberg.h +%{_includedir}/moberg.h %files matlab %defattr(-,root,root,-) -%attr(04755,root,root) %{_libdir}/libmoberg4simulink.so -%attr(04755,root,root) /opt/matlab/src/moberg/* - +%{_libdir}/libmoberg4simulink.so +/opt/matlab/src/moberg/* +%{_includedir}/moberg4simulink.h diff --git a/moberg_config.c b/moberg_config.c index 6349bdeebca06c99a399a4c4016a38b4c73775a6..e4f467d708d8d0b5723b26731da38664272e6c47 100644 --- a/moberg_config.c +++ b/moberg_config.c @@ -24,14 +24,16 @@ struct moberg_config *moberg_config_new() void moberg_config_free(struct moberg_config *config) { - struct device_entry *entry = config->device_head; - while (entry) { - struct device_entry *tmp = entry; - entry = entry->next; - moberg_device_free(tmp->device); - free(tmp); + if (config) { + struct device_entry *entry = config->device_head; + while (entry) { + struct device_entry *tmp = entry; + entry = entry->next; + moberg_device_free(tmp->device); + free(tmp); + } + free(config); } - free(config); } int moberg_config_join(struct moberg_config *dest,