diff options
-rw-r--r-- | README | 9 | ||||
-rw-r--r-- | dispatch.c | 160 | ||||
-rw-r--r-- | dispatch.h | 21 | ||||
-rw-r--r-- | gpib_function.c | 352 | ||||
-rw-r--r-- | gpib_function.mexglx | bin | 0 -> 18750 bytes | |||
-rw-r--r-- | gpib_test.m | 17 | ||||
-rw-r--r-- | lgpib.m | 99 |
7 files changed, 658 insertions, 0 deletions
@@ -0,0 +1,9 @@ +This original files were found at +http://code.google.com/p/matlab-gpib/ + +and cloned with the following command +hg clone https://code.google.com/p/matlab-gpib/ + +This code is distributed under GNU GPL v2 license + + diff --git a/dispatch.c b/dispatch.c new file mode 100644 index 0000000..11f46f5 --- /dev/null +++ b/dispatch.c @@ -0,0 +1,160 @@ +#include "math.h" +#include "mex.h" +#define DISPATCH_C +#include "dispatch.h" + + +/* Matlab Bridge (c) 2010 Richard George, University of Oxford + * + * Compile by typing the following from the Matlab console: + * + * mex [other_module.c] dispatch.c + */ + +int counter = 0; + +extern DispatchTableEntry dispatch_table[]; + + +char *help_help="List the available functions\n"; + +int runDispatchTable(DispatchTableEntry functions[], const char *request, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]); + +int help_nonspecific_handler(int nlhs, mxArray*plhs[], int nrhs, const mxArray* prhs[]); +int help_specific_handler(int nlhs, mxArray*plhs[], int nrhs, const mxArray* prhs[]); + +/* Example dispatch table - define a function called 'help' that can print the contents of the dispatch table */ + +DispatchTableEntry internal_dispatch_table[] = { + { "help" , 0 , 0 , help_nonspecific_handler, &help_help}, + { "help" , 0 , 1 , help_specific_handler, 0 }, + /* Sentinel */ + { 0, 0, 0, 0, 0} +}; + +int help_nonspecific_handler(int nlhs, mxArray*plhs[], int nrhs, const mxArray* prhs[]) { + displayValidFunctions(dispatch_table); +} + +int help_specific_handler(int nlhs, mxArray*plhs[], int nrhs, const mxArray* prhs[]) { + if (nrhs==1) { + const char *request = mxArrayToString(prhs[0]); + mexPrintf("help for %s:\n\n", request); + int i; + for (i=0;dispatch_table[i].function_name!=0;i++) { + if (strcmp(request, dispatch_table[i].function_name)==0) { + if ((*(dispatch_table[i].help))!=0) mexPrintf("%s\n", *(dispatch_table[i].help)); + } + } + } + return 0; +} + +/* This code searches the dispatch table, looking for a match and checking the number of arguments passed */ + +int runDispatchTable(DispatchTableEntry functions[], const char *request, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { + int result; + int i; + int k=0; + + int flag_rhs_error=0; + int flag_lhs_error=0; + + for (i=0;functions[i].function_name!=0;i++) { + /* mexPrintf("runDispatchTable: Comparing %s %s\n", functions[i].function_name, request); */ + if (strcmp(request, functions[i].function_name)==0) { + if (nlhs==functions[i].nlhs) { + + if ((nrhs-1)==functions[i].nrhs) { + result = functions[i].handler(nlhs, &plhs[0], nrhs-1, &prhs[1]); + return 1; + } + else { + flag_rhs_error=1; + k=i; + } + + } + else { + flag_lhs_error=1; + k=i; + } + } + } + + if (flag_rhs_error) mexPrintf("Expecting %d parameter(s) on the right of function %s, but found %d\n", functions[k].nrhs,request, nrhs-1); + if (flag_lhs_error) mexPrintf("Expecting %d parameter(s) on the left of function %s, but found %d\n", functions[k].nlhs,request, nlhs); + + if ((flag_lhs_error==1) || (flag_rhs_error==1)) return -2; + return -1; +} + +/* This function prints the functions defined in a dispatch table passed in as the argument */ + +void displayValidFunctions(DispatchTableEntry functions[]) { + mexPrintf("Available functions are:\n\n"); + int i,j; + char c; + + for (i=0;functions[i].function_name!=0;i++) { + c='A'; + mexPrintf("function "); + + if (functions[i].nlhs>0) { + mexPrintf("["); + for (j=0;j<functions[i].nlhs;j++) { + if (j>0) mexPrintf(","); + mexPrintf("%c",c++); + } + mexPrintf("]="); + } + + mexPrintf("%s(",functions[i].function_name); + + if (functions[i].nrhs>0) { + for (j=0;j<functions[i].nlhs;j++) { + if (j>0) mexPrintf(","); + mexPrintf("%c",c++); + } + } + mexPrintf(")\n"); + if (functions[i].help!=0) { + mexPrintf("\n%s\n\n",*functions[i].help); + } + } +} + +/* The entry point from MATLAB + * + * The first argument from Matlab prhs[0] is used to look-up a value in the dispatch table. If a match is found, the handler function is called with the remaining arguments + */ + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { + + /* Setup on first run */ + if (counter==0) + { + mexPrintf("adding exit hook for gpib_function()\n"); + mexAtExit(ExitFcn); + } + + /* Decode the requested feature */ + if (nrhs>=1) { + const char *request = mxArrayToString(prhs[0]); + int found; + + found=runDispatchTable(internal_dispatch_table, request, nlhs, plhs, nrhs, prhs); + + if (found<0) { + found=runDispatchTable(dispatch_table, request, nlhs, plhs, nrhs, prhs); + } + } + else { + /* Display a help message */ + displayValidFunctions(dispatch_table); + } + + counter++; + return; +} + diff --git a/dispatch.h b/dispatch.h new file mode 100644 index 0000000..8d8c819 --- /dev/null +++ b/dispatch.h @@ -0,0 +1,21 @@ +#ifndef DISPATCH_H +#define DISPATCH_H + +typedef struct tagDispatchTableEntry { + char *function_name; + int nlhs; + int nrhs; + int (*handler)(int,mxArray *[],int,const mxArray *[]); + char **help; +} DispatchTableEntry; + +#ifndef DISPATCH_C +extern int counter; +extern char *help_help; +#endif + +void displayValidFunctions(); +void ExitFcn(); +int help_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]); + +#endif
\ No newline at end of file diff --git a/gpib_function.c b/gpib_function.c new file mode 100644 index 0000000..9bd120f --- /dev/null +++ b/gpib_function.c @@ -0,0 +1,352 @@ +#include "math.h" +#include "string.h" +#include "mex.h" +#include <gpib/ib.h> +#include "dispatch.h" + +/* Matlab:linux-GPIB Bridge (c) 2010 Richard George, University of Oxford + * + * Compile by typing the following from the Matlab console: + * + * mex gpib_function.c dispatch.c -lgpib + */ + +extern DispatchTableEntry dispatch_table[]; + +int verbose = 2; +int write_verbose = 0; + +int timeout_for_double(const double *t); + +int ibfind_handler(int,mxArray*[],int,const mxArray*[]); +int ibsta_handler(int,mxArray*[],int,const mxArray*[]); +int ibcntl_handler(int,mxArray*[],int,const mxArray*[]); +int about_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]); +int quiet_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]); +int verbose_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]); +int ibrdl_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]); +int ibrd_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]); +int ibwrt_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]); +int ibclr_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]); +int ibrsp_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]); +int ibeos_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]); +int ibeot_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]); +int ibtmo_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]); + +char *about_desc = "Matlab to linux-GPIB Bridge (c) 2010 Richard George, University of Oxford\n"; +char *ibfind_desc = "[handle]=ibfind('device_name') looks up a device in the /etc/gpib.conf file, and returns a handle to this device\n"; +char *ibwrt_desc = "[status,written_count]=ibwrt(handle,buffer) writes to GPIB-handle, from buffer, using length of string\n"; +char *ibrdl_desc = "[data,status,read_count]=ibrdl(handle) returns up to length bytes from the specified device\n"; +char *ibrd_desc = "[data,status,read_count]=ibrd(handle,length) returns up to 8192 bytes from the specified device\n"; +char *ibclr_desc = "ibclr(handle) performs a device clear on the specified device\n"; +char *ibeos_desc = "ibeos(handle,end_of_string)\n"; +char *ibeot_desc = "iteot(handle,value)\n"; +char *ibtmo_desc = "ibtmo(handle,timeout) Set the read time-out, in seconds. The resolution of timeout is log-spaced, e.g. 100ms,300ms,1s,3s,10s,30s ...\n"; +char *ibsta_desc = "return the value of ibsta\n"; +char *ibcntl_desc = "return the value of ibcntl\n"; +char *ibrsp_desc = "[result]=ibrsp(handle) performs a serial poll on the specified device\n"; +char *quiet_desc = "turn off debug output from other functions in this library\n"; +char *verbose_desc = "turn on debug output from other functions in this library\n"; + +DispatchTableEntry dispatch_table[] = { + /* + * Add entries here: + * + * Matlab name : # LHS args : # RHS args : C function : Help text */ + { "about" , 0 , 0 , about_handler , &about_desc}, + { "ibfind" , 1 , 1 , ibfind_handler , &ibfind_desc}, + { "ibrdl" , 3 , 2 , ibrdl_handler , &ibrdl_desc}, + { "ibrd" , 3 , 1 , ibrd_handler , &ibrd_desc}, + { "ibsta" , 1 , 0 , ibsta_handler , &ibsta_desc}, + { "ibcntl" , 1 , 0 , ibcntl_handler , &ibcntl_desc}, + { "ibwrt" , 2 , 2 , ibwrt_handler , &ibwrt_desc}, + { "ibclr" , 1 , 1 , ibclr_handler , &ibclr_desc}, + { "ibrsp" , 1 , 1 , ibrsp_handler , &ibrsp_desc}, + { "ibeos" , 1 , 2 , ibeos_handler , &ibeos_desc}, + { "ibeot" , 1 , 2 , ibeot_handler , &ibeot_desc}, + { "ibtmo" , 1 , 2 , ibtmo_handler , &ibtmo_desc}, + { "quiet" , 0 , 0 , quiet_handler , &quiet_desc}, + { "verbose" , 0 , 0 , verbose_handler , &verbose_desc}, + /* Sentinel */ + {0,0,0,0,0} +}; + +int timeout_for_double(const double *t) +{ + const double valid_timeouts[] = {0.0,10e-6,30e-6,100e-6,300e-6,1e-3,3e-3,10e-3,30e-3,100e-3,300e-3,1.0,3.0,10.0,30.0,100.0,300.0,1000.0}; + + if (*t<=0.0) return 0; + if (*t>=1000.0) return 17; + + int i=0; + + while ((valid_timeouts[i]<*t)) i++; + + return i; +} + +int ibeot_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]) +{ + if (nrhs==2) + { + int iresult = -1; + double *handle = mxGetPr(prhs[0]); + double *eot = mxGetPr(prhs[0]); + + iresult = ibeot((int)*handle,(int)eot); + + if (nlhs==1) + { + plhs[0]=mxCreateDoubleScalar((double)iresult); + } + return 0; + + } + + return -1; +} + +int ibeos_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]) +{ + if (nrhs==2) + { + int iresult = -1; + double *handle = mxGetPr(prhs[0]); + double *eos = mxGetPr(prhs[0]); + + iresult = ibtmo((int)*handle,(int)eos); + + if (nlhs==1) + { + plhs[0]=mxCreateDoubleScalar((double)iresult); + } + return 0; + + } + + return -1; +} + +int ibtmo_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]) +{ + + if (nrhs==2) + { + int iresult = -1; + double *handle = mxGetPr(prhs[0]); + double *timeout = mxGetPr(prhs[1]); + int tmo=timeout_for_double(timeout); + if (verbose>3) mexPrintf("Handle = %d, Timeout %g sec => %d\n",(int)*handle,*timeout,tmo); + + iresult = ibtmo((int)*handle,tmo); + + if (nlhs==1) + { + plhs[0]=mxCreateDoubleScalar((double)iresult); + } + return 0; + + } + + return -1; +} + +int ibfind_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]) +{ + const char *device = mxArrayToString(prhs[0]); + if (verbose>2) mexPrintf("ibfind('%s')\n",device); + int result = ibfind(device); + if (verbose>2) mexPrintf("returns %d\n",result); + plhs[0] = mxCreateDoubleScalar((double)result); + return 0; +} + +int ibsta_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]) +{ + if (nrhs==1) + { + plhs[0] = mxCreateDoubleScalar((double)ibsta); + } + + return 0; +} + +int ibcntl_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]) +{ + if (nrhs==1) + { + plhs[0] = mxCreateDoubleScalar((double)ibcntl); + } + + return 0; +} + +int ibwrt_handler(int nlhs, mxArray*plhs[], int nrhs, const mxArray* prhs[]) { + if (nrhs==2) { + double *handle = mxGetPr(prhs[0]); + + mwSize n=mxGetN(prhs[1]), m=mxGetM(prhs[1]); + mxChar *buffer=mxGetChars(prhs[1]); + + char *message = 0; + int i; + + message = calloc(n*m+2, sizeof(char)); + + if (message!=0) { + for (i=0;i<n*m;i++) + { + message[i]=(char)buffer[i]; + if (write_verbose>0) mexPrintf("message[%d]=0x%02X",i,(int)((unsigned char)message[i])); + if ((write_verbose>0) & (message[i]>32) & (message[i]<126)) mexPrintf(" (%c)",message[i]); + if (write_verbose>0) mexPrintf("\n"); + } + message[i]=0; + if (write_verbose>0) mexPrintf("calling ibwrt(handle=%d,message,length=%d)\n",(int)*handle,(int)n*m); + + int result = ibwrt((int)*handle, message, n*m); + + if (write_verbose>0) mexPrintf("ibwrt returns 0x%04X, ibcntl=%d\n",result,ibcntl); + + free(message); + + if (nlhs>=1) plhs[0] = mxCreateDoubleScalar((double)result); + if (nlhs>=2) plhs[1] = mxCreateDoubleScalar((double)ibcntl); + } + + } + + return 0; +} + +int ibrdl_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]) +{ + if (nrhs==2) + { + int i; + double *handle = mxGetPr(prhs[0]); + double *length = mxGetPr(prhs[1]); + + if (nlhs==3) + { + mwSize lengths[2]; + /* mexPrintf("sizeof(mxChar)=%d, sizeof(char)=%d\n",sizeof(mxChar),sizeof(char)); */ + + char *buffer=calloc(((int)*length)+2,sizeof(char)); + int result = ibrd((int)*handle,(void *)buffer,(int)*length); + + /* mexPrintf("result = %d, buffer = %s\n",result,buffer); */ + + lengths[0]=1; + lengths[1]=(mwSize)(ibcntl); + plhs[0]=mxCreateCharArray(2,lengths); + mxChar *mxCharBuffer=(mxChar *)mxGetPr(plhs[0]); + for (i=0;i<ibcntl;i++) mxCharBuffer[i]=(mxChar)buffer[i]; + + free(buffer); + + if (nlhs>=1) plhs[1]=mxCreateDoubleScalar((double)result); + if (nlhs>=2) plhs[2]=mxCreateDoubleScalar((double)ibcntl); + } + + } + + return 0; +} + +int ibrd_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]) +{ + int i; + char *buffer; + + if (nrhs==1) + { + double *handle = mxGetPr(prhs[0]); + + if (nlhs==3) + { + mwSize lengths[2]; + /* mexPrintf("sizeof(mxChar)=%d, sizeof(char)=%d\n",sizeof(mxChar),sizeof(char)); */ + + char *buffer=calloc(8193,sizeof(char)); + int result = ibrd((int)*handle,(void *)buffer,8192); + + /* mexPrintf("result = %d, buffer = %s\n",result,buffer); */ + + lengths[0]=1; + lengths[1]=(mwSize)(ibcntl); + plhs[0]=mxCreateCharArray(2,lengths); + mxChar *mxCharBuffer=(mxChar *)mxGetPr(plhs[0]); + for (i=0;i<ibcntl;i++) mxCharBuffer[i]=(mxChar)buffer[i]; + + free(buffer); + + if (nlhs>=1) plhs[1]=mxCreateDoubleScalar((double)result); + if (nlhs>=2) plhs[2]=mxCreateDoubleScalar((double)ibcntl); + + } + + } + + return 0; +} + +int ibclr_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]) + { + int result = -1; + + if (nrhs==1) { + double *handle = mxGetPr(prhs[0]); + result = ibclr((int)*handle); + + if (nlhs==1) { + plhs[0]=mxCreateDoubleScalar((double)result); + } + } + + return 0; +} + +int ibrsp_handler(int nlhs,mxArray*plhs[],int nrhs,const mxArray* prhs[]) +{ + if (nrhs==1) + { + double *handle = mxGetPr(prhs[0]); + char result = 0; + + ibrsp((int)*handle,&result); + + if (nlhs==1) + { + plhs[0]=mxCreateDoubleScalar((double)result); + } + + } + + return 0; +} + +int quiet_handler(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]) +{ + verbose = 0; + return 0; +} + +int verbose_handler(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]) +{ + verbose = 1; + mexPrintf("gpib_function: debug output is now enabled. Call gpib_function('quiet') to disable.\n"); + return 0; +} + +/* Example handler */ +int about_handler(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]) +{ + mexPrintf("Matlab to Linux-GPIB interface, (c) 2010 Richard George, University of Oxford\n\n"); + return 0; +} + +void ExitFcn() +{ + mexPrintf("Exit function called for gpib_function()\n"); +} diff --git a/gpib_function.mexglx b/gpib_function.mexglx Binary files differnew file mode 100644 index 0000000..dde4198 --- /dev/null +++ b/gpib_function.mexglx diff --git a/gpib_test.m b/gpib_test.m new file mode 100644 index 0000000..8ecf3d4 --- /dev/null +++ b/gpib_test.m @@ -0,0 +1,17 @@ +%% Open scope +% +% get a handle to the oscilloscope from /etc/gpib.conf +% +hscope = gpib_function('ibfind','LECROY_WR'); +%% Write a message +% +% Send the *IDN? message to the scope +% +[status,write_count] = gpib_function('ibwrt',hscope,'*IDN?'); +fprintf('status = 0x%04X\nwrite_count = %d bytes\n',status,write_count); +%% Read the reply +% +% Show the identifier returned by the LeCroy +% +[reply,status,read_count] = gpib_function('ibrdl',hscope,4096); +fprintf('reply = %s\nstatus = 0x%04X\nread_count = %d bytes\n',strtrim(reply),status,read_count);
\ No newline at end of file @@ -0,0 +1,99 @@ +classdef lgpib + + properties + handle + end + + methods + + function [obj] = lgpib(name) + + if exist('gpib_function')~=3 + lgpib.Compile(); + end + + obj.handle = gpib_function('ibfind',name); + + if (obj.handle<0) + fprintf('lgpib Error: Could not open device ''%s''\n',name); + end + + end + + function [status,write_count] = write(obj,message) + + [gpib_status,gpib_count] = gpib_function('ibwrt',obj.handle,message); + + if nargout>=1 + status = gpib_status; + end + + if nargout>=2 + write_count=gpib_count; + end + end + + function [reply,status,read_count] = read(obj,l) + + if nargin==1 + l=8192; + end + + [gpib_reply,gpib_status,gpib_count] = gpib_function('ibrdl',obj.handle,l); + + reply = gpib_reply; + + if nargout>=2 + status = gpib_status; + end + + if nargout>=3 + write_count=gpib_count; + end + end + + function [reply] = query(obj,message,l) + if nargin==2 + l = 8192; + end + + obj.write(message); + + reply = obj.read(l); + end + + function [reply] = set_timeout(obj,tmo) + reply = gpib_function('ibtmo',obj.handle,tmo); + end + + function [reply] = serial_poll(obj) + reply = gpib_function('ibrsp',obj.handle); + end + + function [status] = get_status(obj) + status = gpib_function('ibsta',obj.handle); + end + + function [cntl] = get_counter(obj) + status = gpib_function('ibcntl',obj.handle); + end + + function [status] = clear(obj) + status = gpib_function('ibclr',obj.handle); + end + + function [status] = interface_clear(obj) + status = obj.clear(); + end + + end + + methods (Static) + function Compile + fprintf('Compiling gpib_function.c\n'); + mex gpib_function.c dispatch.c -lgpib + end + end + +end +
\ No newline at end of file |