├── gui ├── tform.mat ├── DMDCalibrate.fig ├── DMDConnect.fig ├── DMDCalibrate.m └── DMDConnect.m ├── misc └── test_img.JPG ├── hidapi ├── hidapi32.dll ├── hidapi64.dll ├── hidapi64.dylib ├── hidapi64_thunk_maci64.dylib ├── hidapi64_thunk_pcwin64.dll ├── hidapi64_thunk_pcwin64.exp ├── hidapi64_thunk_pcwin64.lib ├── hidapi64_thunk_pcwin64.obj ├── hidapi32_proto.m ├── hidapi64mac_proto.m ├── hidapi64_proto.m ├── hidapi.h └── hidapi.m ├── helperFunctions ├── closescreen.m ├── test.m ├── findDMD.m ├── formatRep.m ├── prepBMP.m ├── cSync.m ├── fullscreen.m ├── tb_optparse.m └── statusbar.m ├── DMDIO.m ├── README.md ├── usbDMDIO.m ├── Command.m ├── LICENSE └── DMD.m /gui/tform.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deichrenner/DMDConnect/HEAD/gui/tform.mat -------------------------------------------------------------------------------- /misc/test_img.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deichrenner/DMDConnect/HEAD/misc/test_img.JPG -------------------------------------------------------------------------------- /gui/DMDCalibrate.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deichrenner/DMDConnect/HEAD/gui/DMDCalibrate.fig -------------------------------------------------------------------------------- /gui/DMDConnect.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deichrenner/DMDConnect/HEAD/gui/DMDConnect.fig -------------------------------------------------------------------------------- /hidapi/hidapi32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deichrenner/DMDConnect/HEAD/hidapi/hidapi32.dll -------------------------------------------------------------------------------- /hidapi/hidapi64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deichrenner/DMDConnect/HEAD/hidapi/hidapi64.dll -------------------------------------------------------------------------------- /hidapi/hidapi64.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deichrenner/DMDConnect/HEAD/hidapi/hidapi64.dylib -------------------------------------------------------------------------------- /hidapi/hidapi64_thunk_maci64.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deichrenner/DMDConnect/HEAD/hidapi/hidapi64_thunk_maci64.dylib -------------------------------------------------------------------------------- /hidapi/hidapi64_thunk_pcwin64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deichrenner/DMDConnect/HEAD/hidapi/hidapi64_thunk_pcwin64.dll -------------------------------------------------------------------------------- /hidapi/hidapi64_thunk_pcwin64.exp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deichrenner/DMDConnect/HEAD/hidapi/hidapi64_thunk_pcwin64.exp -------------------------------------------------------------------------------- /hidapi/hidapi64_thunk_pcwin64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deichrenner/DMDConnect/HEAD/hidapi/hidapi64_thunk_pcwin64.lib -------------------------------------------------------------------------------- /hidapi/hidapi64_thunk_pcwin64.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deichrenner/DMDConnect/HEAD/hidapi/hidapi64_thunk_pcwin64.obj -------------------------------------------------------------------------------- /helperFunctions/closescreen.m: -------------------------------------------------------------------------------- 1 | function closescreen() 2 | %CLOSESCREEN Dispose FULLSCREEN() window 3 | % 4 | 5 | global frame_java 6 | try frame_java.dispose(); end 7 | -------------------------------------------------------------------------------- /helperFunctions/test.m: -------------------------------------------------------------------------------- 1 | test = hidapi(0, 1105, 51456, 65, 65) 2 | test.open 3 | test.debug = 1 4 | test.setNonBlocking(1) 5 | buffer = [192, 255, 2, 0, 5, 2]; 6 | test.write(buffer, 0); test.read 7 | 8 | test.close 9 | delete(test) -------------------------------------------------------------------------------- /helperFunctions/findDMD.m: -------------------------------------------------------------------------------- 1 | function [ ind ] = findDMD( ) 2 | %FINDDMD tries to identify the dmd screen by its native resolution 3 | 4 | ge = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(); 5 | gds = ge.getScreenDevices(); 6 | 7 | for i = 1:numel(gds) 8 | height(i) = gds(i).getDisplayMode().getHeight(); 9 | width(i) = gds(i).getDisplayMode().getWidth(); 10 | end 11 | 12 | ind = find(width == 1920 & height == 1080); 13 | 14 | end 15 | 16 | -------------------------------------------------------------------------------- /helperFunctions/formatRep.m: -------------------------------------------------------------------------------- 1 | function x = formatRep(n) 2 | %FORMATREP returns the eRLE repetition number n in required format 3 | % According to the DLPC900 programmers guide p.64, the repetition byte n for 4 | % the enhanced run length encoding has to be in the form 5 | % n < 128 : x = n 6 | % n >= 128 : x = [(n & 0xfF ) | 0x80, (n >> 7)] 7 | % here, &, | and >> are the corresponding operators in C syntax. 8 | % Be careful, the example featured in the programmers guide seems to be 9 | % wrong! 10 | % For reference and to play around you can use the following C code: 11 | % #include 12 | % int main() 13 | % { 14 | % int x = 0; 15 | % int y = 0; 16 | % int z = 500; 17 | % x = ( z & 0x7F ) | 0x80; 18 | % y = z >> 7; 19 | % printf("%x, %x \n", x & 0xff, y & 0xff); 20 | % printf("%d, %d \n", x, y); 21 | % return 0; 22 | % } 23 | % 24 | % Author: Klaus Hueck (e-mail: khueck (at) physik (dot) uni-hamburg (dot) de) 25 | % Version: 0.0.1alpha 26 | % Changes tracker: 28.01.2016 - First version 27 | % License: GPL v3 28 | 29 | if n < 128 30 | x = dec2hex(n, 2); 31 | else 32 | x1 = dec2hex(bitor(bitand(n,127), 128), 2); 33 | x2 = dec2hex(bitshift(n, -7), 2); 34 | x = [x1, x2]; 35 | end 36 | 37 | end -------------------------------------------------------------------------------- /DMDIO.m: -------------------------------------------------------------------------------- 1 | %DMDIO Abstract class definition for DMD input output 2 | % 3 | % Methods:: 4 | % open Open the connection to the DMD 5 | % close Close the connection to the DMD 6 | % read Read data from the DMD 7 | % write Write data to the DMD 8 | % 9 | % Notes:: 10 | % - handle is the connection object 11 | % - The read function should return a uint8 datatype 12 | % - The write function should be given a uint8 datatype as a parameter 13 | % 14 | % This toolbox is based on the hidapi implementation written by Peter Corke 15 | % in the framework of his robotics toolbox. The original source code can be 16 | % found on http://www.petercorke.com/Robotics_Toolbox.html. 17 | % 18 | % Author: Klaus Hueck (e-mail: khueck (at) physik (dot) uni-hamburg (dot) de) 19 | % Version: 0.0.1alpha 20 | % Changes tracker: 28.01.2016 - First version 21 | % License: GPL v3 22 | 23 | classdef DMDIO 24 | properties (Abstract) 25 | % connection handle 26 | handle 27 | end 28 | 29 | methods (Abstract) 30 | % open the DMD connection 31 | open(DMDIO) 32 | % close the DMD connection 33 | close(DMDIO) 34 | % read data from the DMD 35 | read(DMDIO) 36 | % write data to the DMD 37 | write(DMDIO) 38 | end 39 | end -------------------------------------------------------------------------------- /helperFunctions/prepBMP.m: -------------------------------------------------------------------------------- 1 | function data = prepBMP(BMP1) 2 | %prepBMP Adds a header to the matrix BMP and applies RLE to the input matrix 3 | % 4 | % The RLE algorithm is based on http://stackoverflow.com/questions/ 5 | % 12059744/run-length-encoding-in-matlab 6 | % 7 | % Author: Klaus Hueck (e-mail: khueck (at) physik (dot) uni-hamburg (dot) de) 8 | % Version: 0.0.1alpha 9 | % Changes tracker: 28.01.2016 - First version 10 | % License: GPL v3 11 | 12 | bitDepth = 1; 13 | signature = ['53'; '70'; '6C'; '64']; 14 | imageWidth = dec2hex(typecast(uint16(size(BMP1,2)),'uint8'),2); 15 | imageHeight = dec2hex(typecast(uint16(size(BMP1,1)),'uint8'),2); 16 | numOfBytes = dec2hex(typecast(uint32(size(BMP1,1)*size(BMP1,2)*... 17 | bitDepth),'uint8'),2); 18 | backgroundColor = ['00'; '00'; '00'; '00']; 19 | compression = '02'; 20 | 21 | header = [signature; imageWidth; imageHeight; numOfBytes; ... 22 | 'FF'; 'FF'; 'FF'; 'FF'; 'FF'; 'FF'; 'FF'; 'FF'; backgroundColor; ... 23 | '00'; compression; '01'; '00'; '00'; '00'; '00'; '00'; '00'; '00';... 24 | '00'; '00'; '00'; '00'; '00'; '00'; '00'; '00'; '00'; '00'; '00';... 25 | '00'; '00'; '00']; 26 | 27 | % convert input matrix to decimal and transpose for later handling 28 | BMP1 = BMP1'*1; 29 | 30 | % expand to 24bit in 3x8bit decimal notation 31 | BMP24 = dec2hex(BMP1(:),6); 32 | 33 | % clear return variable 34 | data = ''; 35 | 36 | % % compress if whished 37 | if strcmp(compression, '02') 38 | % reshape in order to get 24bit pixel information line by line 39 | [szy, szx] = size(BMP1); 40 | for i = 1:szx 41 | [~, ~, ic] = unique(BMP24((i-1)*szy+1:i*szy,:), 'rows'); 42 | ind = find(diff([ic(1)-1, ic(:)']))+(i-1)*szy; 43 | relMat = [formatRep(diff([ind, i*szy+1])), BMP24(ind,:)]; 44 | data = [data sprintf(relMat(:,:)')]; 45 | end 46 | 47 | % put together header, compressed data and end of image padding 48 | data = [header; char(regexp(data, sprintf('\\w{1,%d}', 2), 'match')'); '00'; '01'; '00']; 49 | else 50 | % merge header and data 51 | data = [header; BMP24;]; 52 | end 53 | 54 | end -------------------------------------------------------------------------------- /helperFunctions/cSync.m: -------------------------------------------------------------------------------- 1 | %Get the Experiment Control status. Might throw an exception. 2 | function [diff, len, reply] = cSync(handles) 3 | %@return: The reply from Experiment Control 4 | %Queries Experiment Control's status. Might throw an exception when 5 | %Experiment Control is not running, so the use of a 6 | %try/catch-construct is highly recommended when using this method. 7 | 8 | %I dont check for an error here, because giving the error to the 9 | %caller function enables a better handling for this event. 10 | 11 | import java.net.*; 12 | import java.io.*; 13 | %Establish connection 14 | socket = Socket(handles.Host, handles.Port); 15 | out = socket.getOutputStream; 16 | in = socket.getInputStream; 17 | out.write(int8(['GETSTATUS' 10])); 18 | %Waiting for messages from Server 19 | while ~(in.available) 20 | end 21 | n = in.available; 22 | %Buffer size = 300 characters 23 | reply = zeros(1,300); 24 | for i = 1:n 25 | reply(i) = in.read(); 26 | end 27 | close(socket); 28 | 29 | b = reply; 30 | 31 | %Get the current time and the ending time; if the 32 | %difference is positive a new measurement gets started. 33 | linebreaks = find(b==10); 34 | tStart = b((linebreaks(2)+12:linebreaks(2)+23))-48; 35 | tNow = b((linebreaks(3)+12:linebreaks(3)+23))-48; 36 | tEnd = b((linebreaks(4)+12:linebreaks(4)+23))-48; 37 | %Convert to DateVectors. I ignore milliseconds. 38 | startVec = [1990, 6, 28, tStart(1)*10+tStart(2), ... 39 | tStart(4)*10+tStart(5), ... 40 | tStart(7)*10+tStart(8)+tStart(10)/10+tStart(11)/100]; 41 | nowVec = [1990, 6, 28, tNow(1)*10+tNow(2), ... 42 | tNow(4)*10+tNow(5), ... 43 | tNow(7)*10+tNow(8)+tNow(10)/10+tNow(11)/100]; 44 | endVec = [1990, 6, 28, tEnd(1)*10+tEnd(2), ... 45 | tEnd(4)*10+tEnd(5), ... 46 | tEnd(7)*10+tEnd(8)+tEnd(10)/10+tEnd(11)/100]; 47 | 48 | diff = etime(endVec, nowVec); 49 | len = etime(endVec, startVec); 50 | %Check if the macine is stopped (if so, the fist seven 51 | %letters are 'Stopped'. In this case, it might be that the 52 | %difference is positive, because i ignored the date before. 53 | if isequal(b(1:7), [83 116 111 112 112 101 100]) 54 | diff = -100; 55 | end; -------------------------------------------------------------------------------- /helperFunctions/fullscreen.m: -------------------------------------------------------------------------------- 1 | function fullscreen(image,device_number) 2 | %FULLSCREEN Display fullscreen true colour images 3 | % FULLSCREEN(C,N) displays matlab image matrix C on display number N 4 | % (which ranges from 1 to number of screens). Image matrix C must be 5 | % the exact resolution of the output screen since no scaling in 6 | % implemented. If fullscreen is activated on the same display 7 | % as the MATLAB window, use ALT-TAB to switch back. 8 | % 9 | % If FULLSCREEN(C,N) is called the second time, the screen will update 10 | % with the new image. 11 | % 12 | % Use CLOSESCREEN() to exit fullscreen. 13 | % 14 | % Requires Matlab 7.x (uses Java Virtual Machine), and has been tested on 15 | % Linux and Windows platforms. 16 | % 17 | % Written by Pithawat Vachiramon 18 | % 19 | % Update (23/3/09): 20 | % - Uses temporary bitmap file to speed up drawing process. 21 | % - Implemeted a fix by Alejandro Camara Iglesias to solve issue with 22 | % non-exclusive-fullscreen-capable screens. 23 | 24 | 25 | ge = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(); 26 | gds = ge.getScreenDevices(); 27 | height = gds(device_number).getDisplayMode().getHeight(); 28 | width = gds(device_number).getDisplayMode().getWidth(); 29 | 30 | if ~isequal(size(image,1),height) 31 | error(['Image must have verticle resolution of ' num2str(height)]); 32 | elseif ~isequal(size(image,2),width) 33 | error(['Image must have horizontal resolution of ' num2str(width)]); 34 | end 35 | 36 | try 37 | imwrite(image,[tempdir 'display.bmp']); 38 | catch 39 | error('Image must be compatible with imwrite()'); 40 | end 41 | 42 | buff_image = javax.imageio.ImageIO.read(java.io.File([tempdir 'display.bmp'])); 43 | 44 | global frame_java; 45 | global icon_java; 46 | global device_number_java; 47 | 48 | if ~isequal(device_number_java, device_number) 49 | try frame_java.dispose(); end 50 | frame_java = []; 51 | device_number_java = device_number; 52 | end 53 | 54 | if ~isequal(class(frame_java), 'javax.swing.JFrame') 55 | frame_java = javax.swing.JFrame(gds(device_number).getDefaultConfiguration()); 56 | frame_java.setUndecorated(true); 57 | icon_java = javax.swing.ImageIcon(buff_image); 58 | label = javax.swing.JLabel(icon_java); 59 | frame_java.getContentPane.add(label); 60 | frame_java.setExtendedState(frame_java.MAXIMIZED_BOTH); 61 | else 62 | icon_java.setImage(buff_image); 63 | end 64 | frame_java.pack 65 | frame_java.repaint 66 | frame_java.show -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DMDConnect 2 | This Matlab package provides a connection to the LightCrafter EVM6500 DLP evaluation platform. 3 | The code is based on the usb communication library hidapi and its Matlab implementation realized by Peter Corke. 4 | For a working progress bar you need to download the textprogressbar function from [FileExchange](http://www.mathworks.com/matlabcentral/fileexchange/28067-text-progress-bar). Copy the file to the helperFunctions folder. 5 | 6 | The most important functions are implemented Command.m and DMD.m. Have a look at the [DLP C900 Programmer's Guide](http://www.ti.com/lit/ug/dlpu018b/dlpu018b.pdf) 7 | for a better reference of the individual commands implemented in this toolbox. 8 | 9 | ## Cross Platform Compatibility 10 | The hidapi implementation should work on Windows, OSX and Linux likewise. However, the communication has only been tested under Windows so far. 11 | 12 | ## Known bugs 13 | * There is still a better error handling needed. 14 | * Some more comments in the code would make it better understandable. 15 | 16 | ## Example 17 | Make the DMDConnect package known to your Matlab installation by adding it to the path. 18 | 19 | Connect the EVM6500 board to your computer. 20 | 21 | Initialize a DMD object: 22 | `d = DMD('debug', 1);` 23 | 24 | Get the firmware version: 25 | `d.fwversion % returns the actual firmware version of the board` 26 | 27 | Set the mode of the DMD to the internal pattern mode. 28 | `d.setMode(1) % Pre-stored pattern mode` 29 | 30 | Activate a checkerboard testpattern. 31 | `d.testPattern(7) % Activate a checkerboard testpattern` 32 | 33 | Put the DMD to sleep. 34 | `d.sleep % Enter standby mode` 35 | 36 | Wake it up again. 37 | `d.wakeup % Wake up again after standby` 38 | 39 | Put the DMD to idle mode in order to equalize the on/off state of single pixels. 40 | `d.idle % Idle mode` 41 | 42 | Put the DMD to active mode back again. 43 | `d.active % Back to active after idle` 44 | 45 | Display some matrix I on the DMD 46 | `I = [ones(500,500) zeros(500,500)];` 47 | `d.display(I);` 48 | 49 | ## Scientific Usage 50 | If you use this code for scientific purpose, please cite it as [![DOI](https://zenodo.org/badge/20887/deichrenner/DMDConnect.svg)](https://zenodo.org/badge/latestdoi/20887/deichrenner/DMDConnect) 51 | 52 | 53 | 54 | ## Licensing 55 | This toolbox is based on the hidapi implementation written by Peter Corke 56 | in the framework of his robotics toolbox. The original source code can be 57 | found on http://www.petercorke.com/Robotics_Toolbox.html. 58 | 59 | Author: Klaus Hueck (e-mail: khueck (at) physik (dot) uni-hamburg (dot) de) 60 | Version: 0.0.1alpha 61 | Changes tracker: 28.01.2016 - First version 62 | License: GPL v3 63 | -------------------------------------------------------------------------------- /hidapi/hidapi32_proto.m: -------------------------------------------------------------------------------- 1 | function [methodinfo,structs,enuminfo,ThunkLibName]=hidapi32_proto 2 | %HIDAPI32_PROTO Create structures to define interfaces found in 'hidapi'. 3 | 4 | %This function was generated by loadlibrary.m parser version 1.1.6.34 on Thu Jan 23 15:02:05 2014 5 | %perl options:'hidapi.i -outfile=hidapi32_proto.m' 6 | ival={cell(1,0)}; % change 0 to the actual number of functions to preallocate the data. 7 | structs=[];enuminfo=[];fcnNum=1; 8 | fcns=struct('name',ival,'calltype',ival,'LHS',ival,'RHS',ival,'alias',ival); 9 | ThunkLibName=[]; 10 | % int hid_init ( void ); 11 | fcns.name{fcnNum}='hid_init'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}=[];fcnNum=fcnNum+1; 12 | % int hid_exit ( void ); 13 | fcns.name{fcnNum}='hid_exit'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}=[];fcnNum=fcnNum+1; 14 | % struct hid_device_info * hid_enumerate ( unsigned short vendor_id , unsigned short product_id ); 15 | fcns.name{fcnNum}='hid_enumerate'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}='hid_device_infoPtr'; fcns.RHS{fcnNum}={'uint16', 'uint16'};fcnNum=fcnNum+1; 16 | % void hid_free_enumeration ( struct hid_device_info * devs ); 17 | fcns.name{fcnNum}='hid_free_enumeration'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}=[]; fcns.RHS{fcnNum}={'hid_device_infoPtr'};fcnNum=fcnNum+1; 18 | % hid_device * hid_open ( unsigned short vendor_id , unsigned short product_id , wchar_t * serial_number ); 19 | fcns.name{fcnNum}='hid_open'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}='hid_device_Ptr'; fcns.RHS{fcnNum}={'uint16', 'uint16', 'uint16Ptr'};fcnNum=fcnNum+1; 20 | % hid_device * hid_open_path ( const char * path ); 21 | fcns.name{fcnNum}='hid_open_path'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}='hid_device_Ptr'; fcns.RHS{fcnNum}={'cstring'};fcnNum=fcnNum+1; 22 | % int hid_write ( hid_device * device , const unsigned char * data , size_t length ); 23 | fcns.name{fcnNum}='hid_write'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint8Ptr', 'uint32'};fcnNum=fcnNum+1; 24 | % int hid_read_timeout ( hid_device * dev , unsigned char * data , size_t length , int milliseconds ); 25 | fcns.name{fcnNum}='hid_read_timeout'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint8Ptr', 'uint32', 'int32'};fcnNum=fcnNum+1; 26 | % int hid_read ( hid_device * device , unsigned char * data , size_t length ); 27 | fcns.name{fcnNum}='hid_read'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint8Ptr', 'uint32'};fcnNum=fcnNum+1; 28 | % int hid_set_nonblocking ( hid_device * device , int nonblock ); 29 | fcns.name{fcnNum}='hid_set_nonblocking'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'int32'};fcnNum=fcnNum+1; 30 | % int hid_send_feature_report ( hid_device * device , const unsigned char * data , size_t length ); 31 | fcns.name{fcnNum}='hid_send_feature_report'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint8Ptr', 'uint32'};fcnNum=fcnNum+1; 32 | % int hid_get_feature_report ( hid_device * device , unsigned char * data , size_t length ); 33 | fcns.name{fcnNum}='hid_get_feature_report'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint8Ptr', 'uint32'};fcnNum=fcnNum+1; 34 | % void hid_close ( hid_device * device ); 35 | fcns.name{fcnNum}='hid_close'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}=[]; fcns.RHS{fcnNum}={'hid_device_Ptr'};fcnNum=fcnNum+1; 36 | % int hid_get_manufacturer_string ( hid_device * device , wchar_t * string , size_t maxlen ); 37 | fcns.name{fcnNum}='hid_get_manufacturer_string'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint16Ptr', 'uint32'};fcnNum=fcnNum+1; 38 | % int hid_get_product_string ( hid_device * device , wchar_t * string , size_t maxlen ); 39 | fcns.name{fcnNum}='hid_get_product_string'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint16Ptr', 'uint32'};fcnNum=fcnNum+1; 40 | % int hid_get_serial_number_string ( hid_device * device , wchar_t * string , size_t maxlen ); 41 | fcns.name{fcnNum}='hid_get_serial_number_string'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint16Ptr', 'uint32'};fcnNum=fcnNum+1; 42 | % int hid_get_indexed_string ( hid_device * device , int string_index , wchar_t * string , size_t maxlen ); 43 | fcns.name{fcnNum}='hid_get_indexed_string'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'int32', 'uint16Ptr', 'uint32'};fcnNum=fcnNum+1; 44 | % const wchar_t * hid_error ( hid_device * device ); 45 | fcns.name{fcnNum}='hid_error'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}='uint16Ptr'; fcns.RHS{fcnNum}={'hid_device_Ptr'};fcnNum=fcnNum+1; 46 | structs.hid_device_.members=struct(''); 47 | structs.hid_device_info.members=struct('path', 'cstring', 'vendor_id', 'uint16', 'product_id', 'uint16', 'serial_number', 'uint16Ptr', 'release_number', 'uint16', 'manufacturer_string', 'uint16Ptr', 'product_string', 'uint16Ptr', 'usage_page', 'uint16', 'usage', 'uint16', 'interface_number', 'int32', 'next', 'hid_device_infoPtr'); 48 | methodinfo=fcns; -------------------------------------------------------------------------------- /usbDMDIO.m: -------------------------------------------------------------------------------- 1 | %usbDMDIO USB interface between MATLAB and the dmd 2 | % 3 | % Methods:: 4 | % 5 | % usbDMDIO Constructor, initialises and opens the usb connection 6 | % delete Destructor, closes the usb connection 7 | % 8 | % open Open a usb connection to the dmd 9 | % close Close the usb connection to the dmd 10 | % read Read data from the dmd through usb 11 | % write Write data to the dmd through usb 12 | % 13 | % Example:: 14 | % usbdmd = usbDMDIO() 15 | % 16 | % Notes:: 17 | % - Uses the hid library implementation in hidapi.m 18 | % 19 | % This toolbox is based on the hidapi implementation written by Peter Corke 20 | % in the framework of his robotics toolbox. The original source code can be 21 | % found on http://www.petercorke.com/Robotics_Toolbox.html. 22 | % 23 | % Author: Klaus Hueck (e-mail: khueck (at) physik (dot) uni-hamburg (dot) de) 24 | % Version: 0.0.1alpha 25 | % Changes tracker: 28.01.2016 - First version 26 | % License: GPL v3 27 | 28 | classdef usbDMDIO < DMDIO 29 | properties 30 | % connection handle 31 | handle 32 | % debug input 33 | debug = 0; 34 | % vendor ID (C900 = 0x0451) 35 | vendorID = 1105; 36 | % product ID (C900 = 0xc900) 37 | productID = 51456; 38 | % read buffer size (needs to be one byte larger than the actual 39 | % buffer, as the hdiapi framework always adds one byte in front for 40 | % the report id) 41 | nReadBuffer = 65; 42 | % write buffer size equals the size of the read buffer 43 | nWriteBuffer = 65; 44 | end 45 | 46 | methods 47 | function dmdIO = usbDMDIO(varargin) 48 | %usbDMDIO.usbDMDIO Create a usbDMDIO object 49 | % 50 | % usbdmd = usbDMDIO(varargin) is an object which 51 | % initialises a usb connection between MATLAB and the dmd 52 | % using hidapi.m. 53 | % 54 | % Notes:: 55 | % - Can take one parameter debug which is a flag specifying 56 | % output printing (0 or 1). 57 | 58 | % make all hidapi relevant functions available to usbDMDIO.m 59 | libDir = strsplit(mfilename('fullpath'), filesep); 60 | % fix fullfile file separation for linux systems 61 | firstsep = ''; 62 | if (isunix == 1) 63 | firstsep = '/'; 64 | end 65 | addpath(fullfile(firstsep, libDir{1:end-1}, 'hidapi')); 66 | 67 | if nargin == 0 68 | dmdIO.debug = 0; 69 | end 70 | if nargin > 0 71 | dmdIO.debug = varargin{1}; 72 | end 73 | if dmdIO.debug > 0 74 | fprintf('usbDMDIO init\n'); 75 | end 76 | % create the usb handle 77 | dmdIO.handle = hidapi(dmdIO.debug,dmdIO.vendorID,dmdIO.productID,dmdIO.nReadBuffer,dmdIO.nWriteBuffer); 78 | % open the dmdIO connection 79 | dmdIO.open; 80 | end 81 | 82 | function delete(dmdIO) 83 | %usbDMDIO.delete Delete the usbDMDIO object 84 | % 85 | % delete(dmdIO) closes the usb connection handle 86 | 87 | if dmdIO.debug > 0 88 | fprintf('usbDMDIO delete\n'); 89 | end 90 | % delete the usb handle 91 | delete(dmdIO.handle) 92 | end 93 | 94 | % open the dmd IO connection 95 | function open(dmdIO) 96 | %usbDMDIO.open Open the usbDMDIO object 97 | % 98 | % usbDMDIO.open() opens the usb handle through the hidapi 99 | % interface. 100 | 101 | if dmdIO.debug > 0 102 | fprintf('usbDMDIO open\n'); 103 | end 104 | % open the usb handle 105 | dmdIO.handle.open; 106 | % % set the connection to nonblocking for read operations 107 | % dmdIO.handle.setNonBlocking(1); 108 | end 109 | 110 | function close(dmdIO) 111 | %usbDMDIO.close Close the usbDMDIO object 112 | % 113 | % usbDMDIO.close() closes the usb handle through the hidapi 114 | % interface. 115 | if dmdIO.debug > 0 116 | fprintf('usbDMDIO close\n'); 117 | end 118 | % close the usb handle 119 | dmdIO.handle.close; 120 | end 121 | 122 | function rmsg = read(dmdIO) 123 | %usbDMDIO.read Read data from the usbDMDIO object 124 | % 125 | % rmsg = usbDMDIO.read() reads data from the dmd through 126 | % usb and returns the data in uint8 format. 127 | % 128 | % Notes:: 129 | % - This function is blocking with no time out in the current 130 | % implementation. 131 | 132 | if dmdIO.debug > 0 133 | fprintf('usbDMDIO read\n'); 134 | end 135 | % read from the usb handle 136 | rmsg = dmdIO.handle.read; 137 | % get the number of read bytes 138 | nLength = double(typecast(uint8(rmsg(3:4)),'uint16')); 139 | % format the read message (2 byte length plus message) 140 | rmsg = rmsg(1:nLength+4); 141 | end 142 | 143 | function write(dmdIO,wmsg) 144 | %usbDMDIO.write Write data to the usbDMDIO object 145 | % 146 | % usbDMDIO.write(wmsg) writes data to the dmd through usb. 147 | % 148 | % Notes:: 149 | % - wmsg is the data to be written to the dmd via usb in 150 | % uint8 format. 151 | 152 | if dmdIO.debug > 0 153 | fprintf('usbDMDIO write\n'); 154 | end 155 | % write to the usb handle using report ID 0 156 | dmdIO.handle.write(wmsg,0); 157 | end 158 | end 159 | end -------------------------------------------------------------------------------- /hidapi/hidapi64mac_proto.m: -------------------------------------------------------------------------------- 1 | function [methodinfo,structs,enuminfo,ThunkLibName]=hidapi64mac_proto 2 | %HIDAPI64MAC_PROTO Create structures to define interfaces found in 'hidapi'. 3 | 4 | %This function was generated by loadlibrary.m parser version 1.1.6.38 on Thu Jan 23 17:27:34 2014 5 | %perl options:'hidapi.i -outfile=hidapi64mac_proto.m -thunkfile=hidapi64_thunk_maci64.c -header=hidapi.h' 6 | ival={cell(1,0)}; % change 0 to the actual number of functions to preallocate the data. 7 | structs=[];enuminfo=[];fcnNum=1; 8 | fcns=struct('name',ival,'calltype',ival,'LHS',ival,'RHS',ival,'alias',ival,'thunkname', ival); 9 | MfilePath=fileparts(mfilename('fullpath')); 10 | ThunkLibName=fullfile(MfilePath,'hidapi64_thunk_maci64'); 11 | % int hid_init ( void ); 12 | fcns.thunkname{fcnNum}='int32voidThunk';fcns.name{fcnNum}='hid_init'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}=[];fcnNum=fcnNum+1; 13 | % int hid_exit ( void ); 14 | fcns.thunkname{fcnNum}='int32voidThunk';fcns.name{fcnNum}='hid_exit'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}=[];fcnNum=fcnNum+1; 15 | % struct hid_device_info * hid_enumerate ( unsigned short vendor_id , unsigned short product_id ); 16 | fcns.thunkname{fcnNum}='voidPtruint16uint16Thunk';fcns.name{fcnNum}='hid_enumerate'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='hid_device_infoPtr'; fcns.RHS{fcnNum}={'uint16', 'uint16'};fcnNum=fcnNum+1; 17 | % void hid_free_enumeration ( struct hid_device_info * devs ); 18 | fcns.thunkname{fcnNum}='voidvoidPtrThunk';fcns.name{fcnNum}='hid_free_enumeration'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}=[]; fcns.RHS{fcnNum}={'hid_device_infoPtr'};fcnNum=fcnNum+1; 19 | % hid_device * hid_open ( unsigned short vendor_id , unsigned short product_id , wchar_t * serial_number ); 20 | fcns.thunkname{fcnNum}='voidPtruint16uint16voidPtrThunk';fcns.name{fcnNum}='hid_open'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='hid_device_Ptr'; fcns.RHS{fcnNum}={'uint16', 'uint16', 'int32Ptr'};fcnNum=fcnNum+1; 21 | % hid_device * hid_open_path ( const char * path ); 22 | fcns.thunkname{fcnNum}='voidPtrcstringThunk';fcns.name{fcnNum}='hid_open_path'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='hid_device_Ptr'; fcns.RHS{fcnNum}={'cstring'};fcnNum=fcnNum+1; 23 | % int hid_write ( hid_device * device , const unsigned char * data , size_t length ); 24 | fcns.thunkname{fcnNum}='int32voidPtrvoidPtrulongThunk';fcns.name{fcnNum}='hid_write'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint8Ptr', 'ulong'};fcnNum=fcnNum+1; 25 | % int hid_read_timeout ( hid_device * dev , unsigned char * data , size_t length , int milliseconds ); 26 | fcns.thunkname{fcnNum}='int32voidPtrvoidPtrulongint32Thunk';fcns.name{fcnNum}='hid_read_timeout'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint8Ptr', 'ulong', 'int32'};fcnNum=fcnNum+1; 27 | % int hid_read ( hid_device * device , unsigned char * data , size_t length ); 28 | fcns.thunkname{fcnNum}='int32voidPtrvoidPtrulongThunk';fcns.name{fcnNum}='hid_read'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint8Ptr', 'ulong'};fcnNum=fcnNum+1; 29 | % int hid_set_nonblocking ( hid_device * device , int nonblock ); 30 | fcns.thunkname{fcnNum}='int32voidPtrint32Thunk';fcns.name{fcnNum}='hid_set_nonblocking'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'int32'};fcnNum=fcnNum+1; 31 | % int hid_send_feature_report ( hid_device * device , const unsigned char * data , size_t length ); 32 | fcns.thunkname{fcnNum}='int32voidPtrvoidPtrulongThunk';fcns.name{fcnNum}='hid_send_feature_report'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint8Ptr', 'ulong'};fcnNum=fcnNum+1; 33 | % int hid_get_feature_report ( hid_device * device , unsigned char * data , size_t length ); 34 | fcns.thunkname{fcnNum}='int32voidPtrvoidPtrulongThunk';fcns.name{fcnNum}='hid_get_feature_report'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint8Ptr', 'ulong'};fcnNum=fcnNum+1; 35 | % void hid_close ( hid_device * device ); 36 | fcns.thunkname{fcnNum}='voidvoidPtrThunk';fcns.name{fcnNum}='hid_close'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}=[]; fcns.RHS{fcnNum}={'hid_device_Ptr'};fcnNum=fcnNum+1; 37 | % int hid_get_manufacturer_string ( hid_device * device , wchar_t * string , size_t maxlen ); 38 | fcns.thunkname{fcnNum}='int32voidPtrvoidPtrulongThunk';fcns.name{fcnNum}='hid_get_manufacturer_string'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'int32Ptr', 'ulong'};fcnNum=fcnNum+1; 39 | % int hid_get_product_string ( hid_device * device , wchar_t * string , size_t maxlen ); 40 | fcns.thunkname{fcnNum}='int32voidPtrvoidPtrulongThunk';fcns.name{fcnNum}='hid_get_product_string'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'int32Ptr', 'ulong'};fcnNum=fcnNum+1; 41 | % int hid_get_serial_number_string ( hid_device * device , wchar_t * string , size_t maxlen ); 42 | fcns.thunkname{fcnNum}='int32voidPtrvoidPtrulongThunk';fcns.name{fcnNum}='hid_get_serial_number_string'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'int32Ptr', 'ulong'};fcnNum=fcnNum+1; 43 | % int hid_get_indexed_string ( hid_device * device , int string_index , wchar_t * string , size_t maxlen ); 44 | fcns.thunkname{fcnNum}='int32voidPtrint32voidPtrulongThunk';fcns.name{fcnNum}='hid_get_indexed_string'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'int32', 'int32Ptr', 'ulong'};fcnNum=fcnNum+1; 45 | % const wchar_t * hid_error ( hid_device * device ); 46 | fcns.thunkname{fcnNum}='voidPtrvoidPtrThunk';fcns.name{fcnNum}='hid_error'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32Ptr'; fcns.RHS{fcnNum}={'hid_device_Ptr'};fcnNum=fcnNum+1; 47 | structs.hid_device_.members=struct(''); 48 | structs.hid_device_info.members=struct('path', 'cstring', 'vendor_id', 'uint16', 'product_id', 'uint16', 'serial_number', 'int32Ptr', 'release_number', 'uint16', 'manufacturer_string', 'int32Ptr', 'product_string', 'int32Ptr', 'usage_page', 'uint16', 'usage', 'uint16', 'interface_number', 'int32', 'next', 'hid_device_infoPtr'); 49 | methodinfo=fcns; -------------------------------------------------------------------------------- /hidapi/hidapi64_proto.m: -------------------------------------------------------------------------------- 1 | function [methodinfo,structs,enuminfo,ThunkLibName]=hidapi64_proto 2 | %HIDAPI64_PROTO Create structures to define interfaces found in 'hidapi'. 3 | 4 | %This function was generated by loadlibrary.m parser version 1.1.6.38 on Thu Jan 23 17:02:57 2014 5 | %perl options:'hidapi.i -outfile=hidapi64_proto.m -thunkfile=hidapi64_thunk_pcwin64.c -header=hidapi.h' 6 | ival={cell(1,0)}; % change 0 to the actual number of functions to preallocate the data. 7 | structs=[];enuminfo=[];fcnNum=1; 8 | fcns=struct('name',ival,'calltype',ival,'LHS',ival,'RHS',ival,'alias',ival,'thunkname', ival); 9 | MfilePath=fileparts(mfilename('fullpath')); 10 | ThunkLibName=fullfile(MfilePath,'hidapi64_thunk_pcwin64'); 11 | % int hid_init ( void ); 12 | fcns.thunkname{fcnNum}='int32voidThunk';fcns.name{fcnNum}='hid_init'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}=[];fcnNum=fcnNum+1; 13 | % int hid_exit ( void ); 14 | fcns.thunkname{fcnNum}='int32voidThunk';fcns.name{fcnNum}='hid_exit'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}=[];fcnNum=fcnNum+1; 15 | % struct hid_device_info * hid_enumerate ( unsigned short vendor_id , unsigned short product_id ); 16 | fcns.thunkname{fcnNum}='voidPtruint16uint16Thunk';fcns.name{fcnNum}='hid_enumerate'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='hid_device_infoPtr'; fcns.RHS{fcnNum}={'uint16', 'uint16'};fcnNum=fcnNum+1; 17 | % void hid_free_enumeration ( struct hid_device_info * devs ); 18 | fcns.thunkname{fcnNum}='voidvoidPtrThunk';fcns.name{fcnNum}='hid_free_enumeration'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}=[]; fcns.RHS{fcnNum}={'hid_device_infoPtr'};fcnNum=fcnNum+1; 19 | % hid_device * hid_open ( unsigned short vendor_id , unsigned short product_id , wchar_t * serial_number ); 20 | fcns.thunkname{fcnNum}='voidPtruint16uint16voidPtrThunk';fcns.name{fcnNum}='hid_open'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='hid_device_Ptr'; fcns.RHS{fcnNum}={'uint16', 'uint16', 'uint16Ptr'};fcnNum=fcnNum+1; 21 | % hid_device * hid_open_path ( const char * path ); 22 | fcns.thunkname{fcnNum}='voidPtrcstringThunk';fcns.name{fcnNum}='hid_open_path'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='hid_device_Ptr'; fcns.RHS{fcnNum}={'cstring'};fcnNum=fcnNum+1; 23 | % int hid_write ( hid_device * device , const unsigned char * data , size_t length ); 24 | fcns.thunkname{fcnNum}='int32voidPtrvoidPtruint64Thunk';fcns.name{fcnNum}='hid_write'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint8Ptr', 'uint64'};fcnNum=fcnNum+1; 25 | % int hid_read_timeout ( hid_device * dev , unsigned char * data , size_t length , int milliseconds ); 26 | fcns.thunkname{fcnNum}='int32voidPtrvoidPtruint64int32Thunk';fcns.name{fcnNum}='hid_read_timeout'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint8Ptr', 'uint64', 'int32'};fcnNum=fcnNum+1; 27 | % int hid_read ( hid_device * device , unsigned char * data , size_t length ); 28 | fcns.thunkname{fcnNum}='int32voidPtrvoidPtruint64Thunk';fcns.name{fcnNum}='hid_read'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint8Ptr', 'uint64'};fcnNum=fcnNum+1; 29 | % int hid_set_nonblocking ( hid_device * device , int nonblock ); 30 | fcns.thunkname{fcnNum}='int32voidPtrint32Thunk';fcns.name{fcnNum}='hid_set_nonblocking'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'int32'};fcnNum=fcnNum+1; 31 | % int hid_send_feature_report ( hid_device * device , const unsigned char * data , size_t length ); 32 | fcns.thunkname{fcnNum}='int32voidPtrvoidPtruint64Thunk';fcns.name{fcnNum}='hid_send_feature_report'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint8Ptr', 'uint64'};fcnNum=fcnNum+1; 33 | % int hid_get_feature_report ( hid_device * device , unsigned char * data , size_t length ); 34 | fcns.thunkname{fcnNum}='int32voidPtrvoidPtruint64Thunk';fcns.name{fcnNum}='hid_get_feature_report'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint8Ptr', 'uint64'};fcnNum=fcnNum+1; 35 | % void hid_close ( hid_device * device ); 36 | fcns.thunkname{fcnNum}='voidvoidPtrThunk';fcns.name{fcnNum}='hid_close'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}=[]; fcns.RHS{fcnNum}={'hid_device_Ptr'};fcnNum=fcnNum+1; 37 | % int hid_get_manufacturer_string ( hid_device * device , wchar_t * string , size_t maxlen ); 38 | fcns.thunkname{fcnNum}='int32voidPtrvoidPtruint64Thunk';fcns.name{fcnNum}='hid_get_manufacturer_string'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint16Ptr', 'uint64'};fcnNum=fcnNum+1; 39 | % int hid_get_product_string ( hid_device * device , wchar_t * string , size_t maxlen ); 40 | fcns.thunkname{fcnNum}='int32voidPtrvoidPtruint64Thunk';fcns.name{fcnNum}='hid_get_product_string'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint16Ptr', 'uint64'};fcnNum=fcnNum+1; 41 | % int hid_get_serial_number_string ( hid_device * device , wchar_t * string , size_t maxlen ); 42 | fcns.thunkname{fcnNum}='int32voidPtrvoidPtruint64Thunk';fcns.name{fcnNum}='hid_get_serial_number_string'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'uint16Ptr', 'uint64'};fcnNum=fcnNum+1; 43 | % int hid_get_indexed_string ( hid_device * device , int string_index , wchar_t * string , size_t maxlen ); 44 | fcns.thunkname{fcnNum}='int32voidPtrint32voidPtruint64Thunk';fcns.name{fcnNum}='hid_get_indexed_string'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'hid_device_Ptr', 'int32', 'uint16Ptr', 'uint64'};fcnNum=fcnNum+1; 45 | % const wchar_t * hid_error ( hid_device * device ); 46 | fcns.thunkname{fcnNum}='voidPtrvoidPtrThunk';fcns.name{fcnNum}='hid_error'; fcns.calltype{fcnNum}='Thunk'; fcns.LHS{fcnNum}='uint16Ptr'; fcns.RHS{fcnNum}={'hid_device_Ptr'};fcnNum=fcnNum+1; 47 | structs.hid_device_.members=struct(''); 48 | structs.hid_device_info.members=struct('path', 'cstring', 'vendor_id', 'uint16', 'product_id', 'uint16', 'serial_number', 'uint16Ptr', 'release_number', 'uint16', 'manufacturer_string', 'uint16Ptr', 'product_string', 'uint16Ptr', 'usage_page', 'uint16', 'usage', 'uint16', 'interface_number', 'int32', 'next', 'hid_device_infoPtr'); 49 | methodinfo=fcns; -------------------------------------------------------------------------------- /helperFunctions/tb_optparse.m: -------------------------------------------------------------------------------- 1 | %OPTPARSE Standard option parser for Toolbox functions 2 | % 3 | % [OPTOUT,ARGS] = TB_OPTPARSE(OPT, ARGLIST) is a generalized option parser for 4 | % Toolbox functions. It supports options that have an assigned value, boolean 5 | % or enumeration types (string or int). 6 | % 7 | % The software pattern is: 8 | % 9 | % function(a, b, c, varargin) 10 | % opt.foo = true; 11 | % opt.bar = false; 12 | % opt.blah = []; 13 | % opt.choose = {'this', 'that', 'other'}; 14 | % opt.select = {'#no', '#yes'}; 15 | % opt = tb_optparse(opt, varargin); 16 | % 17 | % Optional arguments to the function behave as follows: 18 | % 'foo' sets opt.foo <- true 19 | % 'nobar' sets opt.foo <- false 20 | % 'blah', 3 sets opt.blah <- 3 21 | % 'blah', {x,y} sets opt.blah <- {x,y} 22 | % 'that' sets opt.choose <- 'that' 23 | % 'yes' sets opt.select <- 2 (the second element) 24 | % 25 | % and can be given in any combination. 26 | % 27 | % If neither of 'this', 'that' or 'other' are specified then opt.choose <- 'this'. 28 | % If neither of 'no' or 'yes' are specified then opt.select <- 1. 29 | % 30 | % Note: 31 | % - that the enumerator names must be distinct from the field names. 32 | % - that only one value can be assigned to a field, if multiple values 33 | % are required they must be converted to a cell array. 34 | % 35 | % The allowable options are specified by the names of the fields in the 36 | % structure opt. By default if an option is given that is not a field of 37 | % opt an error is declared. 38 | % 39 | % Sometimes it is useful to collect the unassigned options and this can be 40 | % achieved using a second output argument 41 | % [opt,arglist] = tb_optparse(opt, varargin); 42 | % which is a cell array of all unassigned arguments in the order given in 43 | % varargin. 44 | % 45 | % The return structure is automatically populated with fields: verbose and 46 | % debug. The following options are automatically parsed: 47 | % 'verbose' sets opt.verbose <- true 48 | % 'verbose=2' sets opt.verbose <- 2 (very verbose) 49 | % 'verbose=3' sets opt.verbose <- 3 (extremeley verbose) 50 | % 'verbose=4' sets opt.verbose <- 4 (ridiculously verbose) 51 | % 'debug', N sets opt.debug <- N 52 | % 'setopt', S sets opt <- S 53 | % 'showopt' displays opt and arglist 54 | 55 | function [opt,others] = tb_optparse(in, argv) 56 | 57 | arglist = {}; 58 | 59 | argc = 1; 60 | opt = in; 61 | try 62 | opt.verbose = false; 63 | opt.debug = 0; 64 | end 65 | 66 | showopt = false; 67 | 68 | while argc <= length(argv) 69 | option = argv{argc}; 70 | assigned = false; 71 | 72 | if isstr(option) 73 | 74 | switch option 75 | % look for hardwired options 76 | case 'verbose' 77 | opt.verbose = true; 78 | assigned = true; 79 | case 'verbose=2' 80 | opt.verbose = 2; 81 | assigned = true; 82 | case 'verbose=3' 83 | opt.verbose = 3; 84 | assigned = true; 85 | case 'verbose=4' 86 | opt.verbose = 4; 87 | assigned = true; 88 | case 'debug' 89 | opt.debug = argv{argc+1}; 90 | argc = argc+1; 91 | assigned = true; 92 | case 'setopt' 93 | new = argv{argc+1}; 94 | argc = argc+1; 95 | assigned = true; 96 | 97 | 98 | % copy matching field names from new opt struct to current one 99 | for f=fieldnames(new)' 100 | if isfield(opt, f{1}) 101 | opt = setfield(opt, f{1}, getfield(new, f{1})); 102 | end 103 | end 104 | case 'showopt' 105 | showopt = true; 106 | assigned = true; 107 | 108 | otherwise 109 | % does the option match a field in the opt structure? 110 | if isfield(opt, option) 111 | val = getfield(opt, option); 112 | if islogical(val) 113 | % a logical variable can only be set by an option 114 | opt = setfield(opt, option, true); 115 | else 116 | % otherwise grab its value from the next arg 117 | opt = setfield(opt, option, argv{argc+1}); 118 | argc = argc+1; 119 | end 120 | assigned = true; 121 | elseif length(option)>2 && strcmp(option(1:2), 'no') && isfield(opt, option(3:end)) 122 | val = getfield(opt, option(3:end)); 123 | if islogical(val) 124 | % a logical variable can only be set by an option 125 | opt = setfield(opt, option(3:end), false); 126 | assigned = true; 127 | end 128 | else 129 | % the option doesnt match a field name 130 | for field=fieldnames(opt)' 131 | val = getfield(opt, field{1}); 132 | if iscell(val) 133 | for i=1:length(val) 134 | if isempty(val{i}) 135 | continue; 136 | end 137 | if strcmp(option, val{i}) 138 | opt = setfield(opt, field{1}, option); 139 | assigned = true; 140 | break; 141 | elseif val{i}(1) == '#' && strcmp(option, val{i}(2:end)) 142 | opt = setfield(opt, field{1}, i); 143 | assigned = true; 144 | break; 145 | end 146 | end 147 | if assigned 148 | break; 149 | end 150 | end 151 | end 152 | 153 | 154 | end 155 | end % switch 156 | end 157 | if ~assigned 158 | % non matching options are collected 159 | if nargout == 2 160 | arglist = [arglist argv(argc)]; 161 | else 162 | if isstr(argv{argc}) 163 | error(['unknown options: ' argv{argc}]); 164 | end 165 | end 166 | end 167 | 168 | argc = argc + 1; 169 | end % while 170 | 171 | % if enumerator value not assigned, set the default value 172 | for field=fieldnames(in)' 173 | if iscell(getfield(in, field{1})) && iscell(getfield(opt, field{1})) 174 | val = getfield(opt, field{1}); 175 | if isempty(val{1}) 176 | opt = setfield(opt, field{1}, val{1}); 177 | elseif val{1}(1) == '#' 178 | opt = setfield(opt, field{1}, 1); 179 | else 180 | opt = setfield(opt, field{1}, val{1}); 181 | end 182 | end 183 | end 184 | 185 | if showopt 186 | fprintf('Options:\n'); 187 | opt 188 | arglist 189 | end 190 | 191 | if nargout == 2 192 | others = arglist; 193 | end 194 | -------------------------------------------------------------------------------- /gui/DMDCalibrate.m: -------------------------------------------------------------------------------- 1 | function varargout = DMDCalibrate(varargin) 2 | % DMDCALIBRATE MATLAB code for DMDCalibrate.fig 3 | % DMDCALIBRATE, by itself, creates a new DMDCALIBRATE or raises the existing 4 | % singleton*. 5 | % 6 | % H = DMDCALIBRATE returns the handle to a new DMDCALIBRATE or the handle to 7 | % the existing singleton*. 8 | % 9 | % DMDCALIBRATE('CALLBACK',hObject,eventData,handles,...) calls the local 10 | % function named CALLBACK in DMDCALIBRATE.M with the given input arguments. 11 | % 12 | % DMDCALIBRATE('Property','Value',...) creates a new DMDCALIBRATE or raises the 13 | % existing singleton*. Starting from the left, property value pairs are 14 | % applied to the GUI before DMDCalibrate_OpeningFcn gets called. An 15 | % unrecognized property name or invalid value makes property application 16 | % stop. All inputs are passed to DMDCalibrate_OpeningFcn via varargin. 17 | % 18 | % *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one 19 | % instance to run (singleton)". 20 | % 21 | % See also: GUIDE, GUIDATA, GUIHANDLES 22 | 23 | % Edit the above text to modify the response to help DMDCalibrate 24 | 25 | % Last Modified by GUIDE v2.5 09-Mar-2016 16:39:42 26 | 27 | % Begin initialization code - DO NOT EDIT 28 | gui_Singleton = 1; 29 | gui_State = struct('gui_Name', mfilename, ... 30 | 'gui_Singleton', gui_Singleton, ... 31 | 'gui_OpeningFcn', @DMDCalibrate_OpeningFcn, ... 32 | 'gui_OutputFcn', @DMDCalibrate_OutputFcn, ... 33 | 'gui_LayoutFcn', [] , ... 34 | 'gui_Callback', []); 35 | if nargin && ischar(varargin{1}) 36 | gui_State.gui_Callback = str2func(varargin{1}); 37 | end 38 | 39 | if nargout 40 | [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); 41 | else 42 | gui_mainfcn(gui_State, varargin{:}); 43 | end 44 | % End initialization code - DO NOT EDIT 45 | 46 | 47 | % --- Executes just before DMDCalibrate is made visible. 48 | function DMDCalibrate_OpeningFcn(hObject, eventdata, handles, varargin) 49 | % This function has no output args, see OutputFcn. 50 | % hObject handle to figure 51 | % eventdata reserved - to be defined in a future version of MATLAB 52 | % handles structure with handles and user data (see GUIDATA) 53 | % varargin command line arguments to DMDCalibrate (see VARARGIN) 54 | 55 | % Choose default command line output for DMDCalibrate 56 | handles.output = hObject; 57 | 58 | jCalCode = com.mathworks.widgets.SyntaxTextPane; 59 | codeType = jCalCode.M_MIME_TYPE; % ='text/m-MATLAB' 60 | jCalCode.setContentType(codeType) 61 | str = ['dmdsize = [1920, 1080];\n' ... 62 | 'xx = [500 1400 500 1400];\n' ... 63 | 'yy = [200 200 800 800];\n' ... 64 | 'plot(xx,yy,''kx'',''MarkerSize'',10,''LineWidth'',2);\n' ... 65 | 'xlim([1 1920]);\n' ... 66 | 'ylim([1 1080]);\n' ... 67 | 'set(gca,''XTick'',[]) % Remove the ticks in the x axis\n' ... 68 | 'set(gca,''YTick'',[]) % Remove the ticks in the y axis\n' ... 69 | 'text(960,800,''Top'',''FontSize'',16,''HorizontalAlignment'',''center'');\n' ... 70 | 'text(960,200,''Bottom'',''FontSize'',16,''HorizontalAlignment'',''center'');']; 71 | str = sprintf(strrep(str,'%','%%')); 72 | jCalCode.setText(str); 73 | jScrollPane = com.mathworks.mwswing.MJScrollPane(jCalCode); 74 | javacomponent(jScrollPane,[310,313,480,130],gcf); 75 | jCalCode.setCaretPosition(1); 76 | 77 | handles.jCalCode = jCalCode; 78 | 79 | % Update handles structure 80 | guidata(hObject, handles); 81 | 82 | % UIWAIT makes DMDCalibrate wait for user response (see UIRESUME) 83 | % uiwait(handles.figure1); 84 | 85 | 86 | 87 | % --- Outputs from this function are returned to the command line. 88 | function varargout = DMDCalibrate_OutputFcn(hObject, eventdata, handles) 89 | % varargout cell array for returning output args (see VARARGOUT); 90 | % hObject handle to figure 91 | % eventdata reserved - to be defined in a future version of MATLAB 92 | % handles structure with handles and user data (see GUIDATA) 93 | 94 | % Get default command line output from handles structure 95 | varargout{1} = handles.output; 96 | 97 | 98 | % --- Executes on button press in pbGenCalSc. 99 | function pbGenCalSc_Callback(hObject, eventdata, handles) 100 | % hObject handle to pbGenCalSc (see GCBO) 101 | % eventdata reserved - to be defined in a future version of MATLAB 102 | % handles structure with handles and user data (see GUIDATA) 103 | 104 | % set the source image axis as the current axis 105 | axes(handles.axSrc); 106 | % get the command string from the calibration code text window 107 | cmd = get(handles.jCalCode, 'Text'); 108 | % save command as tmp.m file and mlint 109 | fId = fopen([tempdir 'tmp.m'] ,'w'); 110 | fprintf(fId,'%s\n', cmd); 111 | fclose(fId); 112 | msg = checkcode([tempdir 'tmp.m'],'-string'); 113 | delete([tempdir 'tmp.m']); 114 | % if error in code show warning, else execute the command 115 | if msg 116 | warndlg({'The supplied code features an error:', msg}); 117 | else 118 | % evaluate the code 119 | eval(cmd); 120 | % copy axis content and save with required resolution 121 | f1 = figure; 122 | set(f1, 'Visible', 'off'); 123 | copyobj(handles.axSrc,f1); 124 | xlim([1 1920]); 125 | ylim([1 1080]); 126 | set(gca,'XTick',[]) % Remove the ticks in the x axis! 127 | set(gca,'YTick',[]) % Remove the ticks in the y axis 128 | set(gca,'Units','Normalized'); 129 | set(gca,'Position',[0 0 1 1]) % Make the axes occupy the hole figure 130 | t = findall(gca,'type','text'); 131 | fs = get(t, 'FontSize'); 132 | for i = 1:size(t) 133 | set(t(i), 'FontSize', 1.5*fs{i}); 134 | end 135 | m = findall(gca,'type','line'); 136 | ms = get(m, 'MarkerSize'); 137 | set(m, 'MarkerSize', 1.8*ms); 138 | r = 150; % pixels per inch 139 | set(f1, 'PaperUnits', 'inches', 'PaperPosition', [0 0 1920 1080]/r); 140 | print(f1,'-dbmpmono',sprintf('-r%d',r), [tempdir 'tmp.bmp']); 141 | close(f1); 142 | 143 | % load tmp.bmp and assign to handles.calSrc 144 | calSrc = imread([tempdir 'tmp.bmp']); 145 | delete([tempdir 'tmp.bmp']); 146 | handles.calSrc = calSrc; 147 | guidata(hObject, handles); 148 | end 149 | 150 | % --- Executes on button press in pbLoadCalRes. 151 | function pbLoadCalRes_Callback(hObject, eventdata, handles) 152 | % hObject handle to pbLoadCalRes (see GCBO) 153 | % eventdata reserved - to be defined in a future version of MATLAB 154 | % handles structure with handles and user data (see GUIDATA) 155 | [img, dir] = uigetfile('*.png', 'Select Calibration Image...'); 156 | imgpath = [dir filesep img]; 157 | if exist(imgpath, 'file') 158 | calRes = rgb2gray(imread(imgpath)); 159 | axes(handles.axRes); 160 | if any(size(calRes) == [400 400]) 161 | calRes = padarray(calRes, [56 56]); 162 | elseif any(size(calRes) == [200 200]) 163 | calRes = padarray(calRes, 28); 164 | end 165 | imagesc(calRes); axis image; 166 | xlim([1 512]); 167 | ylim([1 512]); 168 | set(gca,'XTick',[]) % Remove the ticks in the x axis 169 | set(gca,'YTick',[]) % Remove the ticks in the y axis 170 | handles.calRes = calRes; % make the image known to the handles struct 171 | guidata(hObject, handles); % update handles struct 172 | end 173 | 174 | % --- Executes on button press in pbPerfCal. 175 | function pbPerfCal_Callback(hObject, eventdata, handles) 176 | % hObject handle to pbPerfCal (see GCBO) 177 | % eventdata reserved - to be defined in a future version of MATLAB 178 | % handles structure with handles and user data (see GUIDATA) 179 | 180 | if isfield(handles, 'calRes') && isfield(handles, 'calSrc') 181 | moving = double(handles.calRes); % calibration image 182 | fixed = double(handles.calSrc); % reference image 183 | 184 | % start referencing tool 185 | [movingPoints,fixedPoints] = cpselect(moving/max(moving(:)), ... 186 | fixed-min(fixed(:)), 'Wait', true); 187 | tform = fitgeotrans(movingPoints, fixedPoints, 'NonreflectiveSimilarity'); 188 | save('tform.mat', 'tform'); 189 | % calculate projection of calibration image to reference image and display 190 | cal = imwarp(moving,tform,'OutputView',imref2d(size(fixed))); 191 | axes(handles.axCal); 192 | imagesc(cal); 193 | set(gca,'XTick',[]) % Remove the ticks in the x axis 194 | set(gca,'YTick',[]) % Remove the ticks in the y axis 195 | handles.Cal = tform; 196 | guidata(hObject, handles); % update handles struct 197 | else 198 | warndlg('You have to specify a calibration image and the resulting picture first'); 199 | end 200 | 201 | 202 | function edtCalCode_Callback(hObject, eventdata, handles) 203 | % hObject handle to edtCalCode (see GCBO) 204 | % eventdata reserved - to be defined in a future version of MATLAB 205 | % handles structure with handles and user data (see GUIDATA) 206 | 207 | % Hints: get(hObject,'String') returns contents of edtCalCode as text 208 | % str2double(get(hObject,'String')) returns contents of edtCalCode as a double 209 | 210 | 211 | % --- Executes during object creation, after setting all properties. 212 | function edtCalCode_CreateFcn(hObject, eventdata, handles) 213 | % hObject handle to edtCalCode (see GCBO) 214 | % eventdata reserved - to be defined in a future version of MATLAB 215 | % handles empty - handles not created until after all CreateFcns called 216 | 217 | % Hint: edit controls usually have a white background on Windows. 218 | % See ISPC and COMPUTER. 219 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) 220 | set(hObject,'BackgroundColor','white'); 221 | end 222 | 223 | % --- Executes on button press in pbDispSrc. 224 | function pbDispSrc_Callback(hObject, eventdata, handles) 225 | % hObject handle to pbDispSrc (see GCBO) 226 | % eventdata reserved - to be defined in a future version of MATLAB 227 | % handles structure with handles and user data (see GUIDATA) 228 | d = DMD('debug',0); 229 | d.display(handles.calSrc); 230 | handles.d = d; 231 | guidata(hObject, handles); % update handles struct 232 | 233 | 234 | 235 | % --- Executes when user attempts to close figure1. 236 | function figure1_CloseRequestFcn(hObject, eventdata, handles) 237 | % hObject handle to figure1 (see GCBO) 238 | % eventdata reserved - to be defined in a future version of MATLAB 239 | % handles structure with handles and user data (see GUIDATA) 240 | 241 | handles.d.delete; 242 | 243 | % Hint: delete(hObject) closes the figure 244 | delete(hObject); 245 | 246 | 247 | -------------------------------------------------------------------------------- /Command.m: -------------------------------------------------------------------------------- 1 | % C900 command construction 2 | % 3 | % Methods:: 4 | % Command Constructor, creates an empty command object 5 | % delete Destructor, clears the command object 6 | % 7 | % addSequenceByte Adds a sequence byte to the command object 8 | % addLength Add the length of the msg to the front of the command object 9 | % addSystemCommand Add a system command to the command object 10 | % addCommand Add a command directly to the command object 11 | % 12 | % clear Clear the command msg 13 | % display Display the command msg (decimal) 14 | % displayHex Display the command msg (hex) 15 | % 16 | % Notes:: 17 | % - Refer to the DLPC900 Programmer's guide for a more detailed 18 | % description of the commands. 19 | % 20 | % Example:: 21 | % cmd = Command(); 22 | % cmd.addLength(); 23 | % 24 | % This toolbox is based on the hidapi implementation written by Peter Corke 25 | % in the framework of his robotics toolbox. The original source code can be 26 | % found on http://www.petercorke.com/Robotics_Toolbox.html. 27 | % 28 | % Author: Klaus Hueck (e-mail: khueck (at) physik (dot) uni-hamburg (dot) de) 29 | % Version: 0.0.1alpha 30 | % Changes tracker: 28.01.2016 - First version 31 | % License: GPL v3 32 | 33 | classdef Command < handle 34 | 35 | %% Communications format (DLPC900 Programmer's guide): 36 | % 37 | % C900 Command Bytes: 38 | % ,------,------,------,------,------,------,------,-------, 39 | % |Byte 0|Byte 1|Byte 2|Byte 3|Byte 4|Byte 5| |Byte 64| 40 | % '------'------'------'------'------'------'------'-------' 41 | % 42 | % Byte 0: Report ID = 0 43 | % 44 | % Byte 1: Flag byte where: 45 | % Bits 2:0 are set to 0x0 for regular DLPC900 operation 46 | % Bit 6 is set to 0x1 to indicate the host wants a reply from the device 47 | % Bit 7 is set to 0x1 to indicate a read transaction 48 | % #define COMMAND_READ 49 | % #define COMMAND_REPLY 50 | % 51 | % Byte 2: Sequence byte: The sequence byte can be a rolling counter. 52 | % It is used primarily when the host wants a response from the DLPC900. 53 | % The DLPC900 will respond with the same sequence byte that the host 54 | % sent. The host can then match the sequence byte from the command it 55 | % sent with the sequence byte from the DLPC900 response. 56 | % 57 | % Byte 3-4: Length: Two byte length denotes the number of data bytes in the sequence and 58 | % excludes the number of bytes in steps 1 through 4. It denotes the total number 59 | % of bytes sent in steps 5 (command bytes). 60 | % 61 | % Byte 5-6: System Command. See DLPC900 Programmer's guide 62 | % 63 | % Byte 7-64: Dependends on the System Command 64 | % 65 | % Example of C900 read operation (**) 66 | % ,-----------,------,----------,-----------,---------------, 67 | % | REPORT ID | FLAG | SEQUENCE | LENGTH(*) | DATA(*) | 68 | % | BYTE | BYTE | BYTE | | | 69 | % |-----------'------'----------'-----------'---------------| 70 | % | 00 | C0 | 11 | 02 00 | 00 11 | 71 | % '-----------'------'----------'-----------'---------------' 72 | % 73 | % Once the host transmits the data over the USB interface, the DLPC900 will respond to the Read 74 | % operation by placing the response data in its internal buffer. The host must then perform a HID driver 75 | % read operation. The table below shows the response data sent back from the DLPC900. 76 | % (a) Report ID: Always set to 0. 77 | % (b) Flag byte: The same as was sent plus error bit. The host may check the error flag (bit 5) as follows. 78 | % (i) 0 = No errors. 79 | % (ii) 1 = Command not found or command failed. 80 | % (c) Sequence byte: The same as was sent. The host may match the sent sequence byte with the 81 | % response sequence byte. 82 | % (d) Length: Number of data bytes. The host must assemble the data according to the definition of the 83 | % command. 84 | % 85 | % Example of C900 read response (**) 86 | % ,-----------,------,----------,-----------,-----------------------, 87 | % | REPORT ID | FLAG | SEQUENCE | LENGTH(*) | DATA(*) | 88 | % | BYTE | BYTE | BYTE | | | 89 | % |-----------'------'----------'-----------'-----------------------| 90 | % | 00 | C0 | 11 | 06 00 | FF 01 FF 01 FF 01 | 91 | % '-----------'------'----------'-----------'-----------------------' 92 | % 93 | % (*) Least significant bit precedes the most significant bit for 94 | % each parameter! 95 | % (**) All values are in HEX notation! 96 | 97 | properties 98 | msg % message to be sent 99 | Mode = 'r'; % mode of this command ('r' (read) / 'w' (write)) initialize to read 100 | Reply = true; % is a reply requestes (true / false) initialize to true 101 | Sequence = 1; % rolling counter for the sequence byte 102 | end 103 | 104 | methods 105 | function cmd = Command(varargin) 106 | % Command.cmd Create an empty command 107 | % 108 | % c = Command(OPTIONS) is an object that represents an C900 command 109 | % 110 | % Example:: 111 | % c = Command(); 112 | 113 | cmd.msg = uint8([]); 114 | end 115 | 116 | function delete(cmd) 117 | %Command.delete Clear command 118 | % 119 | % delete(c) clears the command 120 | 121 | cmd.msg = ''; 122 | end 123 | 124 | function addCommand(cmd,c,d) 125 | %Command.addCommand Add a command 126 | % 127 | % Command.addCommand(v) adds a command to the 128 | % command object. 129 | % 130 | % Notes:: 131 | % - c is a 2x1 cell which holds the usb command which can be 132 | % found in DLPC900 Programmer's guide 133 | % - d is the usb payload 134 | % 135 | % Example:: 136 | % cmd.addCommand({'0x02', '0x05'}, data) 137 | 138 | cmd.msg(5) = uint8(sscanf(c{2}, '%x')); 139 | cmd.msg(6) = uint8(sscanf(c{1}, '%x')); 140 | cmd.addData(d); 141 | cmd.addLength; 142 | cmd.addSequence 143 | cmd.addFlagByte; 144 | end 145 | 146 | function addData(cmd, d) 147 | %Command.addData Adds data to the command string 148 | % 149 | % Command.addData(d) adds data to the command string this has 150 | % to match the usb command. See DLPC900 Programmer's guide. 151 | % 152 | % Example:: 153 | % cmd.addData(d) 154 | 155 | d = uint8(bin2dec(d)); 156 | cmd.msg(7:7+length(d)-1) = d; 157 | end 158 | 159 | function addLength(cmd) 160 | % Command.addLength Add the length 161 | % 162 | % Command.addLength adds the length of the command string set 163 | % via Command.addCommand to the bytes 4 and 4 164 | % 165 | % Example:: 166 | % cmd.addLength 167 | 168 | len = uint16(length(cmd.msg)-4); 169 | cmd.msg(3:4) = typecast(len, 'uint8'); 170 | end 171 | 172 | function addFlagByte(cmd) 173 | % Command.addFlagByte Add the flagbyte 174 | % 175 | % Command.addFlagByte adds the flagbyte of the command to be 176 | % executed 177 | % 178 | % Example:: 179 | % cmd.addFlagByte 180 | 181 | flagstring = ''; 182 | switch cmd.Mode 183 | case 'r' 184 | flagstring = [flagstring, '1']; 185 | case 'w' 186 | flagstring = [flagstring, '0']; 187 | otherwise 188 | error(['The mode specified is not valid! Only ''r'' for read operation ', ... 189 | 'or ''w'' for write operation is allowed.']); 190 | end 191 | switch cmd.Reply 192 | case true 193 | flagstring = [flagstring, '1']; 194 | case false 195 | flagstring = [flagstring, '0']; 196 | otherwise 197 | error('The reply flag can only be true or false!'); 198 | end 199 | flagstring = [flagstring, '000000']; 200 | cmd.msg(1) = bin2dec(flagstring); 201 | end 202 | 203 | function addSequence(cmd) 204 | % Command.addSequence Insert the sequence counter 205 | % 206 | % Command.addSequence insert a sequence counter which can be a 207 | % rolling counter and will be set by the C900 identical in the 208 | % response. 209 | % 210 | % Example:: 211 | % cmd.addSequence() 212 | 213 | cmd.msg(2) = uint8(cmd.Sequence); 214 | end 215 | 216 | function clear(cmd) 217 | % Command.clear Clear command 218 | % 219 | % Commad.clear clears the message 220 | % 221 | % Example:: 222 | % cmd.clear() 223 | 224 | cmd.msg = ''; 225 | end 226 | 227 | function s = char(cmd) 228 | s = ''; 229 | for i=1:length(cmd.msg) 230 | s = [s sprintf(' %d', cmd.msg(i))]; 231 | end 232 | end 233 | 234 | function s = hex(cmd) 235 | s = ''; 236 | for i=1:length(cmd.msg) 237 | s = [s sprintf(' %x', cmd.msg(i))]; 238 | end 239 | end 240 | 241 | function display(cmd) 242 | % Command.display Display the command message (decimal) 243 | % 244 | % Command.display() prints the command message to the MATALB 245 | % command window in decimal format. 246 | % 247 | % Example:: 248 | % cmd.display() 249 | 250 | loose = strcmp( get(0, 'FormatSpacing'), 'loose'); 251 | if loose 252 | disp(' '); 253 | end 254 | disp([inputname(1), ' = ']) 255 | disp( char(cmd) ); 256 | end 257 | 258 | function displayHex(cmd) 259 | % Command.displayHex Display the command message (hex) 260 | % 261 | % Command.displayHex() prints the command message to the MATLAB 262 | % command window in hexadecimal format. 263 | % 264 | % Example:: 265 | % cmd.displayHex() 266 | 267 | loose = strcmp( get(0, 'FormatSpacing'), 'loose'); 268 | if loose 269 | disp(' '); 270 | end 271 | disp([inputname(1), ' = ']) 272 | disp( hex(cmd) ); 273 | end 274 | 275 | 276 | end 277 | end 278 | -------------------------------------------------------------------------------- /hidapi/hidapi.h: -------------------------------------------------------------------------------- 1 | /******************************************************* 2 | HIDAPI - Multi-Platform library for 3 | communication with HID devices. 4 | 5 | Alan Ott 6 | Signal 11 Software 7 | 8 | 8/22/2009 9 | 10 | Copyright 2009, All Rights Reserved. 11 | 12 | At the discretion of the user of this library, 13 | this software may be licensed under the terms of the 14 | GNU Public License v3, a BSD-Style license, or the 15 | original HIDAPI license as outlined in the LICENSE.txt, 16 | LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt 17 | files located at the root of the source distribution. 18 | These files may also be found in the public source 19 | code repository located at: 20 | http://github.com/signal11/hidapi . 21 | ********************************************************/ 22 | 23 | /** @file 24 | * @defgroup API hidapi API 25 | */ 26 | 27 | #ifndef HIDAPI_H__ 28 | #define HIDAPI_H__ 29 | 30 | #include 31 | 32 | #ifdef _WIN32 33 | #define HID_API_EXPORT __declspec(dllexport) 34 | #define HID_API_CALL 35 | #else 36 | #define HID_API_EXPORT /**< API export macro */ 37 | #define HID_API_CALL /**< API call macro */ 38 | #endif 39 | 40 | #define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/ 41 | 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | struct hid_device_; 46 | typedef struct hid_device_ hid_device; /**< opaque hidapi structure */ 47 | 48 | /** hidapi info structure */ 49 | struct hid_device_info { 50 | /** Platform-specific device path */ 51 | char *path; 52 | /** Device Vendor ID */ 53 | unsigned short vendor_id; 54 | /** Device Product ID */ 55 | unsigned short product_id; 56 | /** Serial Number */ 57 | wchar_t *serial_number; 58 | /** Device Release Number in binary-coded decimal, 59 | also known as Device Version Number */ 60 | unsigned short release_number; 61 | /** Manufacturer String */ 62 | wchar_t *manufacturer_string; 63 | /** Product string */ 64 | wchar_t *product_string; 65 | /** Usage Page for this Device/Interface 66 | (Windows/Mac only). */ 67 | unsigned short usage_page; 68 | /** Usage for this Device/Interface 69 | (Windows/Mac only).*/ 70 | unsigned short usage; 71 | /** The USB interface which this logical device 72 | represents. Valid on both Linux implementations 73 | in all cases, and valid on the Windows implementation 74 | only if the device contains more than one interface. */ 75 | int interface_number; 76 | 77 | /** Pointer to the next device */ 78 | struct hid_device_info *next; 79 | }; 80 | 81 | 82 | /** @brief Initialize the HIDAPI library. 83 | 84 | This function initializes the HIDAPI library. Calling it is not 85 | strictly necessary, as it will be called automatically by 86 | hid_enumerate() and any of the hid_open_*() functions if it is 87 | needed. This function should be called at the beginning of 88 | execution however, if there is a chance of HIDAPI handles 89 | being opened by different threads simultaneously. 90 | 91 | @ingroup API 92 | 93 | @returns 94 | This function returns 0 on success and -1 on error. 95 | */ 96 | int HID_API_EXPORT HID_API_CALL hid_init(void); 97 | 98 | /** @brief Finalize the HIDAPI library. 99 | 100 | This function frees all of the static data associated with 101 | HIDAPI. It should be called at the end of execution to avoid 102 | memory leaks. 103 | 104 | @ingroup API 105 | 106 | @returns 107 | This function returns 0 on success and -1 on error. 108 | */ 109 | int HID_API_EXPORT HID_API_CALL hid_exit(void); 110 | 111 | /** @brief Enumerate the HID Devices. 112 | 113 | This function returns a linked list of all the HID devices 114 | attached to the system which match vendor_id and product_id. 115 | If @p vendor_id and @p product_id are both set to 0, then 116 | all HID devices will be returned. 117 | 118 | @ingroup API 119 | @param vendor_id The Vendor ID (VID) of the types of device 120 | to open. 121 | @param product_id The Product ID (PID) of the types of 122 | device to open. 123 | 124 | @returns 125 | This function returns a pointer to a linked list of type 126 | struct #hid_device, containing information about the HID devices 127 | attached to the system, or NULL in the case of failure. Free 128 | this linked list by calling hid_free_enumeration(). 129 | */ 130 | struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id); 131 | 132 | /** @brief Free an enumeration Linked List 133 | 134 | This function frees a linked list created by hid_enumerate(). 135 | 136 | @ingroup API 137 | @param devs Pointer to a list of struct_device returned from 138 | hid_enumerate(). 139 | */ 140 | void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs); 141 | 142 | /** @brief Open a HID device using a Vendor ID (VID), Product ID 143 | (PID) and optionally a serial number. 144 | 145 | If @p serial_number is NULL, the first device with the 146 | specified VID and PID is opened. 147 | 148 | @ingroup API 149 | @param vendor_id The Vendor ID (VID) of the device to open. 150 | @param product_id The Product ID (PID) of the device to open. 151 | @param serial_number The Serial Number of the device to open 152 | (Optionally NULL). 153 | 154 | @returns 155 | This function returns a pointer to a #hid_device object on 156 | success or NULL on failure. 157 | */ 158 | HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, wchar_t *serial_number); 159 | 160 | /** @brief Open a HID device by its path name. 161 | 162 | The path name be determined by calling hid_enumerate(), or a 163 | platform-specific path name can be used (eg: /dev/hidraw0 on 164 | Linux). 165 | 166 | @ingroup API 167 | @param path The path name of the device to open 168 | 169 | @returns 170 | This function returns a pointer to a #hid_device object on 171 | success or NULL on failure. 172 | */ 173 | HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path); 174 | 175 | /** @brief Write an Output report to a HID device. 176 | 177 | The first byte of @p data[] must contain the Report ID. For 178 | devices which only support a single report, this must be set 179 | to 0x0. The remaining bytes contain the report data. Since 180 | the Report ID is mandatory, calls to hid_write() will always 181 | contain one more byte than the report contains. For example, 182 | if a hid report is 16 bytes long, 17 bytes must be passed to 183 | hid_write(), the Report ID (or 0x0, for devices with a 184 | single report), followed by the report data (16 bytes). In 185 | this example, the length passed in would be 17. 186 | 187 | hid_write() will send the data on the first OUT endpoint, if 188 | one exists. If it does not, it will send the data through 189 | the Control Endpoint (Endpoint 0). 190 | 191 | @ingroup API 192 | @param device A device handle returned from hid_open(). 193 | @param data The data to send, including the report number as 194 | the first byte. 195 | @param length The length in bytes of the data to send. 196 | 197 | @returns 198 | This function returns the actual number of bytes written and 199 | -1 on error. 200 | */ 201 | int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length); 202 | 203 | /** @brief Read an Input report from a HID device with timeout. 204 | 205 | Input reports are returned 206 | to the host through the INTERRUPT IN endpoint. The first byte will 207 | contain the Report number if the device uses numbered reports. 208 | 209 | @ingroup API 210 | @param device A device handle returned from hid_open(). 211 | @param data A buffer to put the read data into. 212 | @param length The number of bytes to read. For devices with 213 | multiple reports, make sure to read an extra byte for 214 | the report number. 215 | @param milliseconds timeout in milliseconds or -1 for blocking wait. 216 | 217 | @returns 218 | This function returns the actual number of bytes read and 219 | -1 on error. 220 | */ 221 | int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds); 222 | 223 | /** @brief Read an Input report from a HID device. 224 | 225 | Input reports are returned 226 | to the host through the INTERRUPT IN endpoint. The first byte will 227 | contain the Report number if the device uses numbered reports. 228 | 229 | @ingroup API 230 | @param device A device handle returned from hid_open(). 231 | @param data A buffer to put the read data into. 232 | @param length The number of bytes to read. For devices with 233 | multiple reports, make sure to read an extra byte for 234 | the report number. 235 | 236 | @returns 237 | This function returns the actual number of bytes read and 238 | -1 on error. 239 | */ 240 | int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length); 241 | 242 | /** @brief Set the device handle to be non-blocking. 243 | 244 | In non-blocking mode calls to hid_read() will return 245 | immediately with a value of 0 if there is no data to be 246 | read. In blocking mode, hid_read() will wait (block) until 247 | there is data to read before returning. 248 | 249 | Nonblocking can be turned on and off at any time. 250 | 251 | @ingroup API 252 | @param device A device handle returned from hid_open(). 253 | @param nonblock enable or not the nonblocking reads 254 | - 1 to enable nonblocking 255 | - 0 to disable nonblocking. 256 | 257 | @returns 258 | This function returns 0 on success and -1 on error. 259 | */ 260 | int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock); 261 | 262 | /** @brief Send a Feature report to the device. 263 | 264 | Feature reports are sent over the Control endpoint as a 265 | Set_Report transfer. The first byte of @p data[] must 266 | contain the Report ID. For devices which only support a 267 | single report, this must be set to 0x0. The remaining bytes 268 | contain the report data. Since the Report ID is mandatory, 269 | calls to hid_send_feature_report() will always contain one 270 | more byte than the report contains. For example, if a hid 271 | report is 16 bytes long, 17 bytes must be passed to 272 | hid_send_feature_report(): the Report ID (or 0x0, for 273 | devices which do not use numbered reports), followed by the 274 | report data (16 bytes). In this example, the length passed 275 | in would be 17. 276 | 277 | @ingroup API 278 | @param device A device handle returned from hid_open(). 279 | @param data The data to send, including the report number as 280 | the first byte. 281 | @param length The length in bytes of the data to send, including 282 | the report number. 283 | 284 | @returns 285 | This function returns the actual number of bytes written and 286 | -1 on error. 287 | */ 288 | int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length); 289 | 290 | /** @brief Get a feature report from a HID device. 291 | 292 | Make sure to set the first byte of @p data[] to the Report 293 | ID of the report to be read. Make sure to allow space for 294 | this extra byte in @p data[]. 295 | 296 | @ingroup API 297 | @param device A device handle returned from hid_open(). 298 | @param data A buffer to put the read data into, including 299 | the Report ID. Set the first byte of @p data[] to the 300 | Report ID of the report to be read. 301 | @param length The number of bytes to read, including an 302 | extra byte for the report ID. The buffer can be longer 303 | than the actual report. 304 | 305 | @returns 306 | This function returns the number of bytes read and 307 | -1 on error. 308 | */ 309 | int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length); 310 | 311 | /** @brief Close a HID device. 312 | 313 | @ingroup API 314 | @param device A device handle returned from hid_open(). 315 | */ 316 | void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device); 317 | 318 | /** @brief Get The Manufacturer String from a HID device. 319 | 320 | @ingroup API 321 | @param device A device handle returned from hid_open(). 322 | @param string A wide string buffer to put the data into. 323 | @param maxlen The length of the buffer in multiples of wchar_t. 324 | 325 | @returns 326 | This function returns 0 on success and -1 on error. 327 | */ 328 | int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen); 329 | 330 | /** @brief Get The Product String from a HID device. 331 | 332 | @ingroup API 333 | @param device A device handle returned from hid_open(). 334 | @param string A wide string buffer to put the data into. 335 | @param maxlen The length of the buffer in multiples of wchar_t. 336 | 337 | @returns 338 | This function returns 0 on success and -1 on error. 339 | */ 340 | int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen); 341 | 342 | /** @brief Get The Serial Number String from a HID device. 343 | 344 | @ingroup API 345 | @param device A device handle returned from hid_open(). 346 | @param string A wide string buffer to put the data into. 347 | @param maxlen The length of the buffer in multiples of wchar_t. 348 | 349 | @returns 350 | This function returns 0 on success and -1 on error. 351 | */ 352 | int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen); 353 | 354 | /** @brief Get a string from a HID device, based on its string index. 355 | 356 | @ingroup API 357 | @param device A device handle returned from hid_open(). 358 | @param string_index The index of the string to get. 359 | @param string A wide string buffer to put the data into. 360 | @param maxlen The length of the buffer in multiples of wchar_t. 361 | 362 | @returns 363 | This function returns 0 on success and -1 on error. 364 | */ 365 | int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen); 366 | 367 | /** @brief Get a string describing the last error which occurred. 368 | 369 | @ingroup API 370 | @param device A device handle returned from hid_open(). 371 | 372 | @returns 373 | This function returns a string containing the last error 374 | which occurred or NULL if none has occurred. 375 | */ 376 | HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device); 377 | 378 | #ifdef __cplusplus 379 | } 380 | #endif 381 | 382 | #endif 383 | 384 | -------------------------------------------------------------------------------- /helperFunctions/statusbar.m: -------------------------------------------------------------------------------- 1 | function statusbarHandles = statusbar(varargin) 2 | %statusbar set/get the status-bar of Matlab desktop or a figure 3 | % 4 | % statusbar sets the status-bar text of the Matlab desktop or a figure. 5 | % statusbar accepts arguments in the format accepted by the sprintf 6 | % function and returns the statusbar handle(s), if available. 7 | % 8 | % Syntax: 9 | % statusbarHandle = statusbar(handle, text, sprintf_args...) 10 | % 11 | % statusbar(text, sprintf_args...) sets the status bar text for the 12 | % current figure. If no figure is selected, then one will be created. 13 | % Note that figures with 'HandleVisibility' turned off will be skipped 14 | % (compare findobj & findall). 15 | % In these cases, simply pass their figure handle as first argument. 16 | % text may be a single string argument, or anything accepted by sprintf. 17 | % 18 | % statusbar(handle, ...) sets the status bar text of the figure 19 | % handle (or the figure which contains handle). If the status bar was 20 | % not yet displayed for this figure, it will be created and displayed. 21 | % If text is not supplied, then any existing status bar is erased, 22 | % unlike statusbar(handle, '') which just clears the text. 23 | % 24 | % statusbar(0, ...) sets the Matlab desktop's status bar text. If text is 25 | % not supplied, then any existing text is erased, like statusbar(0, ''). 26 | % 27 | % statusbar([handles], ...) sets the status bar text of all the 28 | % requested handles. 29 | % 30 | % statusbarHandle = statusbar(...) returns the status bar handle 31 | % for the selected figure. The Matlab desktop does not expose its 32 | % statusbar object, so statusbar(0, ...) always returns []. 33 | % If multiple unique figure handles were requested, then 34 | % statusbarHandle is an array of all non-empty status bar handles. 35 | % 36 | % Notes: 37 | % 1) The format statusbarHandle = statusbar(handle) does NOT erase 38 | % any existing statusbar, but just returns the handles. 39 | % 2) The status bar is 20 pixels high across the entire bottom of 40 | % the figure. It hides everything between pixel heights 0-20, 41 | % even parts of uicontrols, regardless of who was created first! 42 | % 3) Three internal handles are exposed to the user (Figures only): 43 | % - CornerGrip: a small square resizing grip on bottom-right corner 44 | % - TextPanel: main panel area, containing the status text 45 | % - ProgressBar: a progress bar within TextPanel (default: invisible) 46 | % 47 | % Examples: 48 | % statusbar; % delete status bar from current figure 49 | % statusbar(0, 'Desktop status: processing...'); 50 | % statusbar([hFig1,hFig2], 'Please wait while processing...'); 51 | % statusbar('Processing %d of %d (%.1f%%)...',idx,total,100*idx/total); 52 | % statusbar('Running... [%s%s]',repmat('*',1,fix(N*idx/total)),repmat('.',1,N-fix(N*idx/total))); 53 | % existingText = get(statusbar(myHandle),'Text'); 54 | % 55 | % Examples customizing the status-bar appearance: 56 | % sb = statusbar('text'); 57 | % set(sb.CornerGrip, 'visible',false); 58 | % set(sb.TextPanel, 'Foreground',java.awt.Color(1,0,0), 'Background',java.awt.Color.cyan, 'ToolTipText','tool tip...') 59 | % set(sb, 'Background',java.awt.Color.cyan); 60 | % 61 | % % sb.ProgressBar is by default invisible, determinite, non-continuous fill, min=0, max=100, initial value=0 62 | % set(sb.ProgressBar, 'Visible',true, 'Minimum',0, 'Maximum',500, 'Value',234); 63 | % set(sb.ProgressBar, 'Visible',true, 'Indeterminate',false); % indeterminate (annimated) 64 | % set(sb.ProgressBar, 'Visible',true, 'StringPainted',true); % continuous fill 65 | % set(sb.ProgressBar, 'Visible',true, 'StringPainted',true, 'string',''); % continuous fill, no percentage text 66 | % 67 | % % Adding a checkbox 68 | % jCheckBox = javax.swing.JCheckBox('cb label'); 69 | % sb.add(jCheckBox,'West'); % Beware: East also works but doesn't resize automatically 70 | % sb.revalidate; % update the display to show the new checkbox 71 | % 72 | % Technical description: 73 | % http://UndocumentedMatlab.com/blog/setting-status-bar-text 74 | % http://UndocumentedMatlab.com/blog/setting-status-bar-components 75 | % 76 | % Notes: 77 | % Statusbar will probably NOT work on Matlab versions earlier than 6.0 (R12) 78 | % In Matlab 6.0 (R12), figure statusbars are not supported (only desktop statusbar) 79 | % 80 | % Warning: 81 | % This code heavily relies on undocumented and unsupported Matlab 82 | % functionality. It works on Matlab 7+, but use at your own risk! 83 | % 84 | % Bugs and suggestions: 85 | % Please send to Yair Altman (altmany at gmail dot com) 86 | % 87 | % Change log: 88 | % 2007-04-25: First version posted on MathWorks file exchange: http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=14773 89 | % 2007-04-29: Added internal ProgressBar; clarified main comment 90 | % 2007-05-04: Added partial support for Matlab 6 91 | % 2011-10-14: Fix for R2011b 92 | % 2014-10-13: Fix for R2014b 93 | % 2015-03-22: Updated usage examples (no changes to the code) 94 | % 95 | % See also: 96 | % ishghandle, sprintf, findjobj (on the file exchange) 97 | 98 | % License to use and modify this code is granted freely without warranty to all, as long as the original author is 99 | % referenced and attributed as such. The original author maintains the right to be solely associated with this work. 100 | 101 | % Copyright (c) 2015, Yair Altman 102 | % All rights reserved. 103 | % 104 | % Redistribution and use in source and binary forms, with or without 105 | % modification, are permitted provided that the following conditions are 106 | % met: 107 | % 108 | % * Redistributions of source code must retain the above copyright 109 | % notice, this list of conditions and the following disclaimer. 110 | % * Redistributions in binary form must reproduce the above copyright 111 | % notice, this list of conditions and the following disclaimer in 112 | % the documentation and/or other materials provided with the distribution 113 | % 114 | % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 115 | % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 116 | % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 117 | % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 118 | % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 119 | % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 120 | % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 121 | % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 122 | % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 123 | % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 124 | % POSSIBILITY OF SUCH DAMAGE. 125 | 126 | % Programmed and Copyright by Yair M. Altman: altmany(at)gmail.com 127 | % $Revision: 1.7 $ $Date: 2015/03/22 11:52:24 $ 128 | 129 | % Check for available Java/AWT (not sure if Swing is really needed so let's just check AWT) 130 | if ~usejava('awt') 131 | error('YMA:statusbar:noJava','statusbar only works on Matlab envs that run on java'); 132 | end 133 | 134 | % Args check 135 | if nargin < 1 | ischar(varargin{1}) %#ok for Matlab 6 compatibility 136 | handles = gcf; % note: this skips over figures with 'HandleVisibility'='off' 137 | else 138 | handles = varargin{1}; 139 | varargin(1) = []; 140 | end 141 | 142 | % Ensure that all supplied handles are valid HG GUI handles (Note: 0 is a valid HG handle) 143 | if isempty(handles) | ~all(ishandle(handles)) %#ok for Matlab 6 compatibility 144 | error('YMA:statusbar:invalidHandle','invalid GUI handle passed to statusbar'); 145 | end 146 | 147 | % Retrieve the requested text string (only process once, for all handles) 148 | if isempty(varargin) 149 | deleteFlag = (nargout==0); 150 | updateFlag = 0; 151 | statusText = ''; 152 | else 153 | deleteFlag = 0; 154 | updateFlag = 1; 155 | statusText = sprintf(varargin{:}); 156 | end 157 | 158 | % Loop over all unique root handles (figures/desktop) of the supplied handles 159 | rootHandles = []; 160 | if any(double(handles)) % non-0, i.e. non-desktop 161 | try 162 | rootHandles = ancestor(handles,'figure'); 163 | if iscell(rootHandles), rootHandles = cell2mat(rootHandles); end 164 | catch 165 | errMsg = 'Matlab version is too old to support figure statusbars'; 166 | % Note: old Matlab version didn't have the ID optional arg in warning/error, so I can't use it here 167 | if any(handles==0) 168 | warning([errMsg, '. Updating the desktop statusbar only.']); %#ok for Matlab 6 compatibility 169 | else 170 | error(errMsg); 171 | end 172 | end 173 | end 174 | rootHandles = unique(rootHandles); 175 | if any(double(handles)==0), rootHandles(end+1)=0; end 176 | statusbarObjs = handle([]); 177 | for rootIdx = 1 : length(rootHandles) 178 | if rootHandles(rootIdx) == 0 179 | setDesktopStatus(statusText); 180 | else 181 | thisStatusbarObj = setFigureStatus(rootHandles(rootIdx), deleteFlag, updateFlag, statusText); %#%#ok<*MSNU> ok 182 | if ~isempty(thisStatusbarObj) 183 | statusbarObjs(end+1) = thisStatusbarObj; 184 | end 185 | end 186 | end 187 | 188 | % If statusbarHandles requested 189 | if nargout 190 | % Return the list of all valid (non-empty) statusbarHandles 191 | statusbarHandles = statusbarObjs; 192 | end 193 | 194 | %end % statusbar %#ok for Matlab 6 compatibility 195 | 196 | %% Set the status bar text of the Matlab desktop 197 | function setDesktopStatus(statusText) 198 | try 199 | % First, get the desktop reference 200 | try 201 | desktop = com.mathworks.mde.desk.MLDesktop.getInstance; % Matlab 7+ 202 | catch 203 | desktop = com.mathworks.ide.desktop.MLDesktop.getMLDesktop; % Matlab 6 204 | end 205 | 206 | % Schedule a timer to update the status text 207 | % Note: can't update immediately, since it will be overridden by Matlab's 'busy' message... 208 | try 209 | t = timer('Name','statusbarTimer', 'TimerFcn',{@setText,desktop,statusText}, 'StartDelay',0.05, 'ExecutionMode','singleShot'); 210 | start(t); 211 | catch 212 | % Probably an old Matlab version that still doesn't have timer 213 | desktop.setStatusText(statusText); 214 | end 215 | catch 216 | %if any(ishandle(hFig)), delete(hFig); end 217 | error('YMA:statusbar:desktopError',['error updating desktop status text: ' lasterr]); 218 | end 219 | %end %#ok for Matlab 6 compatibility 220 | 221 | %% Utility function used as setDesktopStatus's internal timer's callback 222 | function setText(varargin) 223 | if nargin == 4 % just in case... 224 | targetObj = varargin{3}; 225 | statusText = varargin{4}; 226 | targetObj.setStatusText(statusText); 227 | else 228 | % should never happen... 229 | end 230 | %end %#ok for Matlab 6 compatibility 231 | 232 | %% Set the status bar text for a figure 233 | function statusbarObj = setFigureStatus(hFig, deleteFlag, updateFlag, statusText) 234 | try 235 | jFrame = get(handle(hFig),'JavaFrame'); 236 | jFigPanel = get(jFrame,'FigurePanelContainer'); 237 | jRootPane = jFigPanel.getComponent(0).getRootPane; 238 | 239 | % If invalid RootPane, retry up to N times 240 | tries = 10; 241 | while isempty(jRootPane) & tries>0 %#ok for Matlab 6 compatibility - might happen if figure is still undergoing rendering... 242 | drawnow; pause(0.001); 243 | tries = tries - 1; 244 | jRootPane = jFigPanel.getComponent(0).getRootPane; 245 | end 246 | jRootPane = jRootPane.getTopLevelAncestor; 247 | 248 | % Get the existing statusbarObj 249 | statusbarObj = jRootPane.getStatusBar; 250 | 251 | % If status-bar deletion was requested 252 | if deleteFlag 253 | % Non-empty statusbarObj - delete it 254 | if ~isempty(statusbarObj) 255 | jRootPane.setStatusBarVisible(0); 256 | end 257 | elseif updateFlag % status-bar update was requested 258 | % If no statusbarObj yet, create it 259 | if isempty(statusbarObj) 260 | statusbarObj = com.mathworks.mwswing.MJStatusBar; 261 | jProgressBar = javax.swing.JProgressBar; 262 | jProgressBar.setVisible(false); 263 | statusbarObj.add(jProgressBar,'West'); % Beware: East also works but doesn't resize automatically 264 | jRootPane.setStatusBar(statusbarObj); 265 | end 266 | statusbarObj.setText(statusText); 267 | jRootPane.setStatusBarVisible(1); 268 | end 269 | statusbarObj = handle(statusbarObj); 270 | 271 | % Add quick references to the corner grip and status-bar panel area 272 | if ~isempty(statusbarObj) 273 | addOrUpdateProp(statusbarObj,'CornerGrip', statusbarObj.getParent.getComponent(0)); 274 | addOrUpdateProp(statusbarObj,'TextPanel', statusbarObj.getComponent(0)); 275 | addOrUpdateProp(statusbarObj,'ProgressBar', statusbarObj.getComponent(1).getComponent(0)); 276 | end 277 | catch 278 | try 279 | try 280 | title = jFrame.fFigureClient.getWindow.getTitle; 281 | catch 282 | title = jFrame.fHG1Client.getWindow.getTitle; 283 | end 284 | catch 285 | title = get(hFig,'Name'); 286 | end 287 | error('YMA:statusbar:figureError',['error updating status text for figure ' title ': ' lasterr]); 288 | end 289 | %end %#ok for Matlab 6 compatibility 290 | 291 | %% Utility function: add a new property to a handle and update its value 292 | function addOrUpdateProp(handle,propName,propValue) 293 | try 294 | if ~isprop(handle,propName) 295 | schema.prop(handle,propName,'mxArray'); 296 | end 297 | set(handle,propName,propValue); 298 | catch 299 | % never mind... - maybe propName is already in use 300 | %lasterr 301 | end 302 | %end %#ok for Matlab 6 compatibility -------------------------------------------------------------------------------- /gui/DMDConnect.m: -------------------------------------------------------------------------------- 1 | function varargout = DMDConnect(varargin) 2 | % DMDCONNECT MATLAB code for DMDConnect.fig 3 | % DMDCONNECT, by itself, creates a new DMDCONNECT or raises the existing 4 | % singleton*. 5 | % 6 | % H = DMDCONNECT returns the handle to a new DMDCONNECT or the handle to 7 | % the existing singleton*. 8 | % 9 | % DMDCONNECT('CALLBACK',hObject,eventData,handles,...) calls the local 10 | % function named CALLBACK in DMDCONNECT.M with the given input arguments. 11 | % 12 | % DMDCONNECT('Property','Value',...) creates a new DMDCONNECT or raises the 13 | % existing singleton*. Starting from the left, property value pairs are 14 | % applied to the GUI before DMDConnect_OpeningFcn gets called. An 15 | % unrecognized property name or invalid value makes property application 16 | % stop. All inputs are passed to DMDConnect_OpeningFcn via varargin. 17 | % 18 | % *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one 19 | % instance to run (singleton)". 20 | % 21 | % See also: GUIDE, GUIDATA, GUIHANDLES 22 | 23 | % Edit the above text to modify the response to help DMDConnect 24 | 25 | % Last Modified by GUIDE v2.5 04-Mar-2016 23:14:41 26 | 27 | % Begin initialization code - DO NOT EDIT 28 | gui_Singleton = 1; 29 | gui_State = struct('gui_Name', mfilename, ... 30 | 'gui_Singleton', gui_Singleton, ... 31 | 'gui_OpeningFcn', @DMDConnect_OpeningFcn, ... 32 | 'gui_OutputFcn', @DMDConnect_OutputFcn, ... 33 | 'gui_LayoutFcn', [], ... 34 | 'gui_Callback', []); 35 | if nargin && ischar(varargin{1}) 36 | gui_State.gui_Callback = str2func(varargin{1}); 37 | end 38 | 39 | if nargout 40 | [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); 41 | else 42 | gui_mainfcn(gui_State, varargin{:}); 43 | end 44 | % End initialization code - DO NOT EDIT 45 | 46 | 47 | % --- Executes just before DMDConnect is made visible. 48 | function DMDConnect_OpeningFcn(hObject, eventdata, handles, varargin) 49 | % This function has no output args, see OutputFcn. 50 | % hObject handle to figure 51 | % eventdata reserved - to be defined in a future version of MATLAB 52 | % handles structure with handles and user data (see GUIDATA) 53 | % varargin command line arguments to DMDConnect (see VARARGIN) 54 | 55 | % define default values 56 | handles.Host = '134.100.104.14'; 57 | handles.Port = 8093; 58 | 59 | % Choose default command line output for DMDConnect 60 | handles.output = hObject; 61 | 62 | % insert coding window with example code 63 | jCalCode = com.mathworks.widgets.SyntaxTextPane; 64 | codeType = jCalCode.M_MIME_TYPE; % ='text/m-MATLAB' 65 | jCalCode.setContentType(codeType) 66 | str = ['dmdsz = [1080, 1920]; % define dmd size\n' ... 67 | '[xx, yy] = meshgrid(-dmdsz(2)/2:dmdsz(2)/2-1,-dmdsz(1)/2:dmdsz(1)/2-1);\n' ... 68 | 'r = sqrt(xx.^2 + yy.^2); % generate radial vector\n' ... 69 | 'I = zeros(dmdsz); % define image to be displayed\n' ... 70 | 'I(r>200) = 1; % set ring\n' ... 71 | 'imagesc(I); % show preview']; 72 | str = sprintf(strrep(str,'%','%%')); 73 | jCalCode.setText(str); 74 | jScrollPane = com.mathworks.mwswing.MJScrollPane(jCalCode); 75 | javacomponent(jScrollPane,[185,230,650,450],gcf); 76 | jCalCode.setCaretPosition(1); 77 | handles.jCalCode = jCalCode; 78 | 79 | % do not show any java related warning 80 | warning('off', 'MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame'); 81 | 82 | % initialize the pause/stop buttons 83 | set(handles.tgbStop, 'Enable', 'off'); 84 | set(handles.tgbPause, 'Enable', 'off'); 85 | 86 | % connect to the dmd 87 | d = DMD('debug', 0); 88 | % put the dmd to sleep 89 | d.sleep; 90 | % make dmd object known to the handles struct 91 | handles.d = d; 92 | 93 | % mark the sync flag as not being in sync 94 | handles.inSync = 0; 95 | 96 | % Update handles structure 97 | guidata(hObject, handles); 98 | 99 | % UIWAIT makes DMDConnect wait for user response (see UIRESUME) 100 | % uiwait(handles.figure1); 101 | 102 | % --- This function sets the actual status of the DMD in the status bar 103 | function setDMDstatus(handles) 104 | % status cell strin containing the dmd status information 105 | % handles structure with handles and user data (see GUIDATA) 106 | % insert status bar in the bottom region of the window 107 | 108 | % read status and show 109 | status = handles.d.status; 110 | statusbar(['Status: ' status{:}]); %#ok<*MSNU> 111 | 112 | 113 | % --- Outputs from this function are returned to the command line. 114 | function varargout = DMDConnect_OutputFcn(hObject, eventdata, handles) 115 | % varargout cell array for returning output args (see VARARGOUT); 116 | % hObject handle to figure 117 | % eventdata reserved - to be defined in a future version of MATLAB 118 | % handles structure with handles and user data (see GUIDATA) 119 | 120 | % Get default command line output from handles structure 121 | varargout{1} = handles.output; 122 | 123 | % make the statusbar visible and show status of the dmd 124 | d = handles.d; 125 | status = d.status; 126 | old_pos = get(gcf,'Position'); 127 | set(gcf,'Position',1.05.*old_pos); 128 | set(gcf,'Position',old_pos); 129 | stat = statusbar(['Status: ' status{:}]); %#ok<*MSNU> 130 | set(stat.CornerGrip, 'visible', false); %#ok<*MSNU> 131 | handles.stat = stat; 132 | guidata(hObject, handles); 133 | 134 | 135 | % --- Executes on button press in pbGenBMP. 136 | function pbGenBMP_Callback(hObject, eventdata, handles) 137 | % hObject handle to pbGenBMP (see GCBO) 138 | % eventdata reserved - to be defined in a future version of MATLAB 139 | % handles structure with handles and user data (see GUIDATA) 140 | 141 | % set the source image axis as the current axis 142 | axes(handles.axImg); 143 | % get the command string from the calibration code text window 144 | cmd = get(handles.jCalCode, 'Text'); 145 | % save command as tmp.m file and mlint 146 | fId = fopen([tempdir 'tmp.m'] ,'w'); 147 | fprintf(fId,'%s\n', cmd); 148 | fclose(fId); 149 | msg = checkcode([tempdir 'tmp.m'],'-string'); 150 | delete([tempdir 'tmp.m']); 151 | % if error in code show warning, else execute the command 152 | if msg 153 | warndlg({'The supplied code features an error:', msg}); 154 | else 155 | % evaluate the code 156 | eval(cmd); 157 | xlim([1 1920]); 158 | ylim([1 1080]); 159 | set(gca,'XTick',[]) % Remove the ticks in the x axis! 160 | set(gca,'YTick',[]) % Remove the ticks in the y axis 161 | set(gca,'Units','Normalized'); 162 | handles.BMP = I; 163 | handles.isUploaded = 0; 164 | guidata(hObject, handles); 165 | end 166 | 167 | % --- Executes on button press in pbSelBMP. 168 | function pbSelBMP_Callback(hObject, ~, handles) 169 | % hObject handle to pbSelBMP (see GCBO) 170 | % eventdata reserved - to be defined in a future version of MATLAB 171 | % handles structure with handles and user data (see GUIDATA) 172 | [img, dir] = uigetfile('*.bmp', 'Select Image...'); 173 | imgpath = [dir filesep img]; 174 | if exist(imgpath, 'file') 175 | I = imread(imgpath); 176 | if size(I,3) > 1 177 | I = rgb2gray(I); 178 | end 179 | axes(handles.axImg); 180 | imagesc(I); 181 | set(gca,'XTick',[]) % Remove the ticks in the x axis 182 | set(gca,'YTick',[]) % Remove the ticks in the y axis 183 | handles.BMP = I; % make the image known to the handles struct 184 | handles.isUploaded = 0; 185 | guidata(hObject, handles); % update handles struct 186 | end 187 | 188 | 189 | % --- Executes on button press in tgbSync. 190 | function tgbSync_Callback(hObject, eventdata, handles) 191 | % hObject handle to tgbSync (see GCBO) 192 | % eventdata reserved - to be defined in a future version of MATLAB 193 | % handles structure with handles and user data (see GUIDATA) 194 | 195 | % Hint: get(hObject,'Value') returns toggle state of tgbSync 196 | if get(hObject, 'Value') 197 | % check, if cycle is running 198 | nextc = cSync(handles); 199 | 200 | % if not, show warning and set sync toggle button to off 201 | if nextc == -100 202 | warndlg('Cycle is not running. Start cycle and retry!'); 203 | set(hObject, 'Value', 'Off') 204 | else 205 | while get(hObject, 'Value') 206 | % if it is running, pause the dmd 207 | tgbPause_Callback(hObject, eventdata, handles) 208 | % check the status, wait and play the 209 | % dmd sequence 210 | if ~handles.inSync 211 | [nextc, len] = cSync(handles); 212 | statusbar('Wait for cycle to end...'); 213 | if floor(nextc) > 1 214 | for i = 1:floor(nextc-1.5) 215 | set(handles.stat.ProgressBar, 'Visible', true, 'Minimum',0, ... 216 | 'Maximum', len, 'Value', len-nextc+i); 217 | pause(1); 218 | end 219 | end 220 | handles.inSync = 1; 221 | guidata(hObject, handles); % update handles struct 222 | end 223 | [nextc, len] = cSync(handles); 224 | tstart = timer('StartDelay',nextc+str2double(get(handles.edDelayT, 'String')) ... 225 | ,'ExecutionMode', 'singleShot'); 226 | tstart.TimerFcn = {@tgbPlay_Callback, handles}; 227 | tstop = timer('StartDelay',nextc+str2double(get(handles.edDelayT, 'String'))+ ... 228 | str2double(get(handles.edOnT, 'String')), ... 229 | 'ExecutionMode', 'singleShot'); 230 | tstop.TimerFcn = {@tgbPause_Callback, handles}; 231 | 232 | tprog = timer('StartDelay',nextc,'ExecutionMode', 'fixedRate', ... 233 | 'TasksToExecute', floor(len-1), 'Period', 1); 234 | tprog.TimerFcn = {@cProgressBar_Callback, handles}; 235 | 236 | start(tstart); 237 | start(tstop); 238 | start(tprog); 239 | wait(tstop); 240 | end 241 | wait(tprog); 242 | handles.inSync = 0; 243 | guidata(hObject, handles); % update handles struct 244 | set(handles.stat.ProgressBar, 'Visible', false); 245 | end 246 | end 247 | 248 | 249 | function cProgressBar_Callback(hObject, eventdata, handles) 250 | % hObject handle to edDelayT (see GCBO) 251 | % eventdata reserved - to be defined in a future version of MATLAB 252 | % handles structure with handles and user data (see GUIDATA) 253 | % nextc seconds until next cycle start 254 | % len cycle length in total in seconds 255 | 256 | [nc, l] = cSync(handles); 257 | set(handles.stat.ProgressBar, 'Visible', true, 'Minimum',0, ... 258 | 'Maximum', l, 'Value', l - nc); 259 | 260 | 261 | function edDelayT_Callback(hObject, eventdata, handles) 262 | % hObject handle to edDelayT (see GCBO) 263 | % eventdata reserved - to be defined in a future version of MATLAB 264 | % handles structure with handles and user data (see GUIDATA) 265 | 266 | % Hints: get(hObject,'String') returns contents of edDelayT as text 267 | % str2double(get(hObject,'String')) returns contents of edDelayT as a double 268 | 269 | 270 | % --- Executes during object creation, after setting all properties. 271 | function edDelayT_CreateFcn(hObject, eventdata, handles) 272 | % hObject handle to edDelayT (see GCBO) 273 | % eventdata reserved - to be defined in a future version of MATLAB 274 | % handles empty - handles not created until after all CreateFcns called 275 | 276 | % Hint: edit controls usually have a white background on Windows. 277 | % See ISPC and COMPUTER. 278 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) 279 | set(hObject,'BackgroundColor','white'); 280 | end 281 | 282 | 283 | 284 | function edOnT_Callback(hObject, eventdata, handles) 285 | % hObject handle to edOnT (see GCBO) 286 | % eventdata reserved - to be defined in a future version of MATLAB 287 | % handles structure with handles and user data (see GUIDATA) 288 | 289 | % Hints: get(hObject,'String') returns contents of edOnT as text 290 | % str2double(get(hObject,'String')) returns contents of edOnT as a double 291 | 292 | 293 | % --- Executes during object creation, after setting all properties. 294 | function edOnT_CreateFcn(hObject, eventdata, handles) 295 | % hObject handle to edOnT (see GCBO) 296 | % eventdata reserved - to be defined in a future version of MATLAB 297 | % handles empty - handles not created until after all CreateFcns called 298 | 299 | % Hint: edit controls usually have a white background on Windows. 300 | % See ISPC and COMPUTER. 301 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) 302 | set(hObject,'BackgroundColor','white'); 303 | end 304 | 305 | 306 | % --- Executes on button press in tgbPlay. 307 | function tgbPlay_Callback(hObject, eventdata, handles) 308 | % hObject handle to tgbPlay (see GCBO) 309 | % eventdata reserved - to be defined in a future version of MATLAB 310 | % handles structure with handles and user data (see GUIDATA) 311 | 312 | % Hint: get(hObject,'Value') returns toggle state of tgbPlay 313 | if isfield(handles, 'BMP') 314 | set(handles.tgbStop, 'Enable', 'on'); 315 | set(handles.tgbPause, 'Enable', 'on'); 316 | set(handles.tgbPlay, 'Enable', 'off'); 317 | d = handles.d; 318 | stat = handles.stat; 319 | if d.sleeping 320 | d.wakeup 321 | set(stat.ProgressBar, 'Visible', true, ... 322 | 'Minimum',0, 'Maximum',100, 'Value', 20); 323 | statusbar('Woke up DMD...'); 324 | end 325 | if handles.isUploaded 326 | d.patternControl(2); 327 | else 328 | statusbar('Generate BMP and upload...'); 329 | d.display(handles.BMP); 330 | set(stat.ProgressBar, 'Value', 60); 331 | statusbar('Uploaded...'); 332 | handles.isUploaded = 1; 333 | guidata(hObject, handles); 334 | end 335 | setDMDstatus(handles); 336 | else 337 | warndlg('You have to specify an image first!'); 338 | end 339 | 340 | % --- Executes on button press in tgbPause. 341 | function tgbPause_Callback(hObject, eventdata, handles) 342 | % hObject handle to tgbPause (see GCBO) 343 | % eventdata reserved - to be defined in a future version of MATLAB 344 | % handles structure with handles and user data (see GUIDATA) 345 | 346 | % Hint: get(hObject,'Value') returns toggle state of tgbPause 347 | set(handles.tgbStop, 'Enable', 'on'); 348 | set(handles.tgbPause, 'Enable', 'off'); 349 | set(handles.tgbPlay, 'Enable', 'on'); 350 | d = handles.d; 351 | d.patternControl(1); 352 | setDMDstatus(handles); 353 | 354 | 355 | % --- Executes on button press in tgbStop. 356 | function tgbStop_Callback(hObject, eventdata, handles) 357 | % hObject handle to tgbStop (see GCBO) 358 | % eventdata reserved - to be defined in a future version of MATLAB 359 | % handles structure with handles and user data (see GUIDATA) 360 | 361 | % Hint: get(hObject,'Value') returns toggle state of tgbStop 362 | set(handles.tgbStop, 'Enable', 'off'); 363 | set(handles.tgbPause, 'Enable', 'off'); 364 | set(handles.tgbPlay, 'Enable', 'on'); 365 | d = handles.d; 366 | d.patternControl(0); 367 | d.sleep; 368 | handles.isUploaded = 0; 369 | setDMDstatus(handles); 370 | guidata(hObject, handles); % update handles struct 371 | 372 | 373 | % --- Executes on button press in pbFlatF. 374 | function pbFlatF_Callback(hObject, eventdata, handles) 375 | % hObject handle to pbFlatF (see GCBO) 376 | % eventdata reserved - to be defined in a future version of MATLAB 377 | % handles structure with handles and user data (see GUIDATA) 378 | 379 | -------------------------------------------------------------------------------- /hidapi/hidapi.m: -------------------------------------------------------------------------------- 1 | %hidpi Interface to the hidapi library 2 | % 3 | % Methods:: 4 | % hidpi Constructor, loads the hidapi library 5 | % delete Destructor, closes any open hid connection 6 | % 7 | % open Open the hid device with vendor and product ID 8 | % close Close the hid device connection 9 | % read Read data from the hid device 10 | % write Write data to the hid device 11 | % 12 | % getHIDInfoString Get the relevant hid info from the hid device 13 | % getManufacturersString Get the manufacturers string from the hid device 14 | % getProductString Get the product string from the hid device 15 | % getSerialNumberString Get the serial number from the hid device 16 | % setNonBlocking Set non blocking hid read 17 | % init Init the hidapi (executed in open by default) 18 | % exit Exit the hidapi 19 | % error Return the error string 20 | % enumerate Enumerate the connected hid devices 21 | % 22 | % Example:: 23 | % hid = hidapi(1,1684,0005,1024,1024) 24 | % 25 | % Notes:: 26 | % - Developed from the hidapi available from http://www.signal11.us/oss/hidapi/ 27 | % - Windows: need the hidapi.dll file 28 | % - Mac: need the hidapi.dylib file. Will also need Xcode installed to run load library 29 | % - Linux: will need to compile on host system and copy the resulting .so file 30 | % - Code still untested on Mac and Linux 31 | % 32 | % This toolbox is based on the hidapi implementation written by Peter Corke 33 | % in the framework of his robotics toolbox. The original source code can be 34 | % found on http://www.petercorke.com/Robotics_Toolbox.html. 35 | % 36 | % Author: Klaus Hueck (e-mail: khueck (at) physik (dot) uni-hamburg (dot) de) 37 | % Version: 0.0.1alpha 38 | % Changes tracker: 28.01.2016 - First version 39 | % License: GPL v3 40 | 41 | classdef hidapi < handle 42 | properties 43 | % connection handle 44 | handle 45 | % debug input 46 | debug = 0; 47 | % vendor ID 48 | vendorID = 0; 49 | % product ID 50 | productID = 0; 51 | % read buffer size 52 | nReadBuffer = 256; 53 | % write buffer size 54 | nWriteBuffer = 256; 55 | % shared library 56 | slib = 'hidapi'; 57 | % shared library header 58 | sheader = 'hidapi.h'; 59 | % isOpen flag 60 | isOpen = 0; 61 | end 62 | 63 | methods 64 | 65 | function hid = hidapi(debug,vendorID,productID,nReadBuffer,nWriteBuffer) 66 | %hidapi.hidapi Create a hidapi library interface object 67 | % 68 | % hid = hidapi(debug,vendorID,productID,nReadBuffer,nWriteButter) 69 | % is an object which initialises the hidapi from the corresponding 70 | % OS library. Other parameters are also initialised. Some OS 71 | % checking is required in this function to load the correct 72 | % library. 73 | % 74 | % Notes:: 75 | % - debug is a flag specifying output printing (0 or 1). 76 | % - vendorID is the vendor ID of the hid device (decimal not hex). 77 | % - productID is the product ID of the hid device (decimal not hex). 78 | % - nReadBuffer is the length of the read buffer. 79 | % - nWriteBuffer is the length of the write buffer. 80 | 81 | % make all hidapi relevant library files known to the matlab path 82 | libDir = strsplit(mfilename('fullpath'), filesep); 83 | % fix fullfile file separation for linux systems 84 | firstsep = ''; 85 | if (isunix == 1) 86 | firstsep = '/'; 87 | end 88 | addpath(fullfile(firstsep, libDir{1:end-1})); 89 | 90 | hid.debug = debug; 91 | if hid.debug > 0 92 | fprintf('hidapi init\n'); 93 | end 94 | if nargin > 1 95 | hid.vendorID = vendorID; 96 | hid.productID = productID; 97 | hid.nReadBuffer = nReadBuffer; 98 | hid.nWriteBuffer = nWriteBuffer; 99 | end 100 | % disable the type not found for structure warning 101 | warning('off','MATLAB:loadlibrary:TypeNotFoundForStructure'); 102 | % check if the library is loaded 103 | if ~libisloaded('hidapiusb') 104 | % check the operating system type and load slib 105 | if (ispc == 1) 106 | % check the bit version 107 | if (strcmp(mexext,'mexw32')) 108 | hid.slib = 'hidapi32'; 109 | % load the library via the proto file 110 | loadlibrary(hid.slib,@hidapi32_proto,'alias','hidapiusb') 111 | end 112 | 113 | if (strcmp(mexext,'mexw64')) 114 | hid.slib = 'hidapi64'; 115 | % load the library via the proto file 116 | loadlibrary(hid.slib,@hidapi64_proto,'alias','hidapiusb') 117 | end 118 | else if (ismac == 1) 119 | hid.slib = 'hidapi64'; 120 | % load the library via the proto file 121 | loadlibrary(hid.slib,@hidapi64mac_proto,'alias','hidapiusb'); 122 | else if (isunix == 1) 123 | hid.slib = 'hidapi.so'; 124 | % load the shared library 125 | loadlibrary(hid.slib,hid.sheader,'alias','hidapiusb'); 126 | end 127 | end 128 | end 129 | end 130 | % remove the library extension 131 | hid.slib = 'hidapiusb'; 132 | end 133 | 134 | function delete(hid) 135 | %hidapi.delete Delete hid object 136 | % 137 | % delete(hid) closes an open hid device connection. 138 | % 139 | % Notes:: 140 | % - You cannot unloadlibrary in this function as the object is 141 | % still present in the MATLAB work space. 142 | 143 | if hid.debug > 0 144 | fprintf('hidapi delete\n'); 145 | end 146 | if hid.isOpen == 1 147 | % close the open connection 148 | hid.close(); 149 | end 150 | end 151 | 152 | function open(hid) 153 | %hidapi.open Open a hid object 154 | % 155 | % hid.open() opens a connection with a hid device with the 156 | % initialised values of vendorID and productID from the hidapi 157 | % constructor. 158 | % 159 | % Notes:: 160 | % - The pointer return value from this library call is always 161 | % null so it is not possible to know if the open was 162 | % successful. 163 | % - The final paramter to the open hidapi library call has 164 | % different types depending on OS. In windows it is uint16 but 165 | % linux/mac it is int32. 166 | 167 | if hid.debug > 0 168 | fprintf('hidapi open\n'); 169 | end 170 | % create a null pointer for the hid_open function (depends on OS) 171 | if (ispc == 1) 172 | pNull = libpointer('uint16Ptr'); 173 | end 174 | if ((ismac == 1) || (isunix == 1)) 175 | pNull = libpointer('int32Ptr'); 176 | end 177 | % open the hid interface 178 | [hid.handle,value] = calllib(hid.slib,'hid_open',uint16(hid.vendorID),uint16(hid.productID),pNull); 179 | % set open flag 180 | hid.isOpen = 1; 181 | end 182 | 183 | function close(hid) 184 | %hidapi.close Close hid object 185 | % 186 | % hid.close() closes the connection to a hid device. 187 | 188 | if hid.debug > 0 189 | fprintf('hidapi close\n'); 190 | end 191 | if hid.isOpen == 1 192 | % close the connect 193 | calllib(hid.slib,'hid_close',hid.handle); 194 | % clear open flag 195 | hid.isOpen = 0; 196 | end 197 | end 198 | 199 | 200 | function rmsg = read(hid) 201 | %hidapi.rmsg Read from hid object 202 | % 203 | % rmsg = hid.read() reads from a hid device and returns the 204 | % read bytes. Will print an error if no data was read. 205 | 206 | if hid.debug > 0 207 | fprintf('hidapi read\n'); 208 | end 209 | % read buffer of nReadBuffer length 210 | buffer = zeros(1,hid.nReadBuffer); 211 | % create a unit8 pointer 212 | pbuffer = libpointer('uint8Ptr', uint8(buffer)); 213 | % read data from HID deivce 214 | [res,h] = calllib(hid.slib,'hid_read_timeout',hid.handle, ... 215 | pbuffer,uint64(length(buffer)),1000); 216 | % check the response 217 | if res == 0 218 | fprintf('hidapi read returned no data\n'); 219 | end 220 | % return the string value 221 | rmsg = pbuffer.Value; 222 | end 223 | 224 | function write(hid,wmsg,reportID) 225 | %hidapi.write Write to hid object 226 | % 227 | % hid.write() writes to a hid device. Will print an error if 228 | % there is a mismach between the buffer size and the reported 229 | % number of bytes written. 230 | 231 | if hid.debug > 0 232 | fprintf('hidapi write\n'); 233 | end 234 | % append a 0 at the front for HID report ID 235 | wmsg = [reportID wmsg]; 236 | % pad with zeros for nWriteBuffer length 237 | wmsg(end+(hid.nWriteBuffer-length(wmsg))) = 0; 238 | % create a unit8 pointer 239 | pbuffer = libpointer('uint8Ptr', uint8(wmsg)); 240 | % write the message 241 | [res,h] = calllib(hid.slib,'hid_write',hid.handle,pbuffer,uint64(length(wmsg))); 242 | % check the response 243 | if res ~= length(wmsg) 244 | fprintf('hidapi write error: wrote %d, sent %d\n',(length(wmsg)-1),res); 245 | end 246 | end 247 | 248 | function str = getHIDInfoString(hid,info) 249 | %hidapi.getHIDInfoString get hid information from object 250 | % 251 | % hid.getHIDInfoString(info) gets the corresponding hid info 252 | % from the hid device 253 | % 254 | % Notes:: 255 | % - info is the hid information string. 256 | 257 | if hid.debug > 0 258 | fprintf(['hidapi ' info '\n']); 259 | end 260 | % read buffer nReadBuffer length 261 | buffer = zeros(1,hid.nReadBuffer); 262 | % create a unit16 pointer (depends on OS) 263 | if (ispc == 1) 264 | pbuffer = libpointer('uint16Ptr', uint16(buffer)); 265 | else if ((ismac == 1) || (isunix == 1)) 266 | pbuffer = libpointer('int32Ptr', int32(buffer)); 267 | end 268 | end 269 | % get the HID info string 270 | [res,h] = calllib(hid.slib,info,hid.handle,pbuffer,uint64(length(buffer))); 271 | % check the response 272 | if res ~= 0 273 | fprintf(['hidapi ' info ' error\n']); 274 | end 275 | % return the string value 276 | str = sprintf('%s',char(pbuffer.Value)); 277 | end 278 | 279 | function str = getManufacturersString(hid) 280 | %hidapi.getManufacturersString get manufacturers string from hid object 281 | % 282 | % hid.getManufacturersString() returns the manufacturers string 283 | % from the hid device using getHIDInfoString. 284 | 285 | str = getHIDInfoString(hid,'hid_get_manufacturer_string'); 286 | end 287 | 288 | function str = getProductString(hid) 289 | %hidapi.getProductString get product string from hid object 290 | % 291 | % hid.getProductString() returns the product string from the 292 | % hid device using getProductString. 293 | 294 | str = getHIDInfoString(hid,'hid_get_product_string'); 295 | end 296 | 297 | function str = getSerialNumberString(hid) 298 | %hidapi.getSerialNumberString get product string from hid object 299 | % 300 | % hid.getSerialNumberString() returns the serial number string 301 | % from the hid device using getSerialNumberString. 302 | 303 | str = getHIDInfoString(hid,'hid_get_serial_number_string'); 304 | end 305 | 306 | function setNonBlocking(hid,nonblock) 307 | %hidapi.setNonBlocking sets non blocking on the hid object 308 | % 309 | % hid.setNonBlocking(nonblock) sets the non blocking flag on 310 | % the hid device connection. 311 | % 312 | % Notes:: 313 | % nonblock - 0 disables nonblocking, 1 enables nonblocking 314 | 315 | if hid.debug > 0 316 | fprintf('hidapi setNonBlocking\n'); 317 | end 318 | % set non blocking 319 | [res,h] = calllib(hid.slib,'hid_set_nonblocking',hid.handle,uint64(nonblock)); 320 | % check the response 321 | if res ~= 0 322 | fprintf('hidapi setNonBlocking error\n'); 323 | end 324 | end 325 | 326 | function init(hid) 327 | %hidapi.init Init hidapi 328 | % 329 | % hid.init() inits the hidapi library. This is called 330 | % automatically in the library itself with the open function. 331 | % 332 | % Notes:: 333 | % - You should not have to call this function directly. 334 | 335 | if hid.debug > 0 336 | fprintf('hidapi init\n'); 337 | end 338 | res = calllib(hid.slib,'hid_init'); 339 | if res ~= 0 340 | fprintf('hidapi init error\n'); 341 | end 342 | end 343 | 344 | function exit(hid) 345 | %hidapi.exit Exit hidapi 346 | % 347 | % hid.exit() exits the hidapi library. 348 | % 349 | % Notes:: 350 | % - You should not have to call this function directly. 351 | 352 | if hid.debug > 0 353 | fprintf('hidapi exit\n'); 354 | end 355 | res = calllib(hid.slib,'hid_exit'); 356 | if res ~= 0 357 | fprintf('hidapi exit error\n'); 358 | end 359 | end 360 | 361 | function str = error(hid) 362 | %hidapi.error Output the hid object error string 363 | % 364 | % hid.error() returns the hid device error string if a function 365 | % produced an error. 366 | % 367 | % Notes:: 368 | % - This function must be called explicitly if you think an 369 | % error was generated from the hid device. 370 | 371 | if hid.debug > 0 372 | fprintf('hidapi error\n'); 373 | end 374 | [h,str] = calllib(hid.slib,'hid_error',hid.handle); 375 | end 376 | 377 | function str = enumerate(hid,vendorID,productID) 378 | %hidapi.enumerate Enumerates the hid object 379 | % 380 | % str = hid.enumerate(vendorID,productID) enumerates the hid 381 | % device with the given vendorID and productID and returns a 382 | % string with the returned hid information. 383 | % 384 | % Notes:: 385 | % - vendorID is the vendor ID (in decimal not hex). 386 | % - productID is the vendor ID (in decimal not hex). 387 | % - Using a vendorID and productID of (0,0) will enumerate all 388 | % connected hid devices. 389 | % - MATLAB does not have the hid_device_infoPtr struct so some 390 | % of the returned information will need to be resized and cast 391 | % into uint8 or chars. 392 | 393 | if hid.debug > 0 394 | fprintf('hidapi enumerate\n'); 395 | end 396 | % enumerate the hid devices 397 | str = calllib(u.slib,'hid_enumerate',uint16(vendorID),uint16(productID)); 398 | end 399 | end 400 | end -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Please cite this contribution in case of scientific usage as indicated in 2 | the corresponding README.md on https://github.com/deichrenner/DMDConnect. 3 | 4 | GNU GENERAL PUBLIC LICENSE 5 | Version 2, June 1991 6 | 7 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 8 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 9 | Everyone is permitted to copy and distribute verbatim copies 10 | of this license document, but changing it is not allowed. 11 | 12 | Preamble 13 | 14 | The licenses for most software are designed to take away your 15 | freedom to share and change it. By contrast, the GNU General Public 16 | License is intended to guarantee your freedom to share and change free 17 | software--to make sure the software is free for all its users. This 18 | General Public License applies to most of the Free Software 19 | Foundation's software and to any other program whose authors commit to 20 | using it. (Some other Free Software Foundation software is covered by 21 | the GNU Lesser General Public License instead.) You can apply it to 22 | your programs, too. 23 | 24 | When we speak of free software, we are referring to freedom, not 25 | price. Our General Public Licenses are designed to make sure that you 26 | have the freedom to distribute copies of free software (and charge for 27 | this service if you wish), that you receive source code or can get it 28 | if you want it, that you can change the software or use pieces of it 29 | in new free programs; and that you know you can do these things. 30 | 31 | To protect your rights, we need to make restrictions that forbid 32 | anyone to deny you these rights or to ask you to surrender the rights. 33 | These restrictions translate to certain responsibilities for you if you 34 | distribute copies of the software, or if you modify it. 35 | 36 | For example, if you distribute copies of such a program, whether 37 | gratis or for a fee, you must give the recipients all the rights that 38 | you have. You must make sure that they, too, receive or can get the 39 | source code. And you must show them these terms so they know their 40 | rights. 41 | 42 | We protect your rights with two steps: (1) copyright the software, and 43 | (2) offer you this license which gives you legal permission to copy, 44 | distribute and/or modify the software. 45 | 46 | Also, for each author's protection and ours, we want to make certain 47 | that everyone understands that there is no warranty for this free 48 | software. If the software is modified by someone else and passed on, we 49 | want its recipients to know that what they have is not the original, so 50 | that any problems introduced by others will not reflect on the original 51 | authors' reputations. 52 | 53 | Finally, any free program is threatened constantly by software 54 | patents. We wish to avoid the danger that redistributors of a free 55 | program will individually obtain patent licenses, in effect making the 56 | program proprietary. To prevent this, we have made it clear that any 57 | patent must be licensed for everyone's free use or not licensed at all. 58 | 59 | The precise terms and conditions for copying, distribution and 60 | modification follow. 61 | 62 | GNU GENERAL PUBLIC LICENSE 63 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 64 | 65 | 0. This License applies to any program or other work which contains 66 | a notice placed by the copyright holder saying it may be distributed 67 | under the terms of this General Public License. The "Program", below, 68 | refers to any such program or work, and a "work based on the Program" 69 | means either the Program or any derivative work under copyright law: 70 | that is to say, a work containing the Program or a portion of it, 71 | either verbatim or with modifications and/or translated into another 72 | language. (Hereinafter, translation is included without limitation in 73 | the term "modification".) Each licensee is addressed as "you". 74 | 75 | Activities other than copying, distribution and modification are not 76 | covered by this License; they are outside its scope. The act of 77 | running the Program is not restricted, and the output from the Program 78 | is covered only if its contents constitute a work based on the 79 | Program (independent of having been made by running the Program). 80 | Whether that is true depends on what the Program does. 81 | 82 | 1. You may copy and distribute verbatim copies of the Program's 83 | source code as you receive it, in any medium, provided that you 84 | conspicuously and appropriately publish on each copy an appropriate 85 | copyright notice and disclaimer of warranty; keep intact all the 86 | notices that refer to this License and to the absence of any warranty; 87 | and give any other recipients of the Program a copy of this License 88 | along with the Program. 89 | 90 | You may charge a fee for the physical act of transferring a copy, and 91 | you may at your option offer warranty protection in exchange for a fee. 92 | 93 | 2. You may modify your copy or copies of the Program or any portion 94 | of it, thus forming a work based on the Program, and copy and 95 | distribute such modifications or work under the terms of Section 1 96 | above, provided that you also meet all of these conditions: 97 | 98 | a) You must cause the modified files to carry prominent notices 99 | stating that you changed the files and the date of any change. 100 | 101 | b) You must cause any work that you distribute or publish, that in 102 | whole or in part contains or is derived from the Program or any 103 | part thereof, to be licensed as a whole at no charge to all third 104 | parties under the terms of this License. 105 | 106 | c) If the modified program normally reads commands interactively 107 | when run, you must cause it, when started running for such 108 | interactive use in the most ordinary way, to print or display an 109 | announcement including an appropriate copyright notice and a 110 | notice that there is no warranty (or else, saying that you provide 111 | a warranty) and that users may redistribute the program under 112 | these conditions, and telling the user how to view a copy of this 113 | License. (Exception: if the Program itself is interactive but 114 | does not normally print such an announcement, your work based on 115 | the Program is not required to print an announcement.) 116 | 117 | These requirements apply to the modified work as a whole. If 118 | identifiable sections of that work are not derived from the Program, 119 | and can be reasonably considered independent and separate works in 120 | themselves, then this License, and its terms, do not apply to those 121 | sections when you distribute them as separate works. But when you 122 | distribute the same sections as part of a whole which is a work based 123 | on the Program, the distribution of the whole must be on the terms of 124 | this License, whose permissions for other licensees extend to the 125 | entire whole, and thus to each and every part regardless of who wrote it. 126 | 127 | Thus, it is not the intent of this section to claim rights or contest 128 | your rights to work written entirely by you; rather, the intent is to 129 | exercise the right to control the distribution of derivative or 130 | collective works based on the Program. 131 | 132 | In addition, mere aggregation of another work not based on the Program 133 | with the Program (or with a work based on the Program) on a volume of 134 | a storage or distribution medium does not bring the other work under 135 | the scope of this License. 136 | 137 | 3. You may copy and distribute the Program (or a work based on it, 138 | under Section 2) in object code or executable form under the terms of 139 | Sections 1 and 2 above provided that you also do one of the following: 140 | 141 | a) Accompany it with the complete corresponding machine-readable 142 | source code, which must be distributed under the terms of Sections 143 | 1 and 2 above on a medium customarily used for software interchange; or, 144 | 145 | b) Accompany it with a written offer, valid for at least three 146 | years, to give any third party, for a charge no more than your 147 | cost of physically performing source distribution, a complete 148 | machine-readable copy of the corresponding source code, to be 149 | distributed under the terms of Sections 1 and 2 above on a medium 150 | customarily used for software interchange; or, 151 | 152 | c) Accompany it with the information you received as to the offer 153 | to distribute corresponding source code. (This alternative is 154 | allowed only for noncommercial distribution and only if you 155 | received the program in object code or executable form with such 156 | an offer, in accord with Subsection b above.) 157 | 158 | The source code for a work means the preferred form of the work for 159 | making modifications to it. For an executable work, complete source 160 | code means all the source code for all modules it contains, plus any 161 | associated interface definition files, plus the scripts used to 162 | control compilation and installation of the executable. However, as a 163 | special exception, the source code distributed need not include 164 | anything that is normally distributed (in either source or binary 165 | form) with the major components (compiler, kernel, and so on) of the 166 | operating system on which the executable runs, unless that component 167 | itself accompanies the executable. 168 | 169 | If distribution of executable or object code is made by offering 170 | access to copy from a designated place, then offering equivalent 171 | access to copy the source code from the same place counts as 172 | distribution of the source code, even though third parties are not 173 | compelled to copy the source along with the object code. 174 | 175 | 4. You may not copy, modify, sublicense, or distribute the Program 176 | except as expressly provided under this License. Any attempt 177 | otherwise to copy, modify, sublicense or distribute the Program is 178 | void, and will automatically terminate your rights under this License. 179 | However, parties who have received copies, or rights, from you under 180 | this License will not have their licenses terminated so long as such 181 | parties remain in full compliance. 182 | 183 | 5. You are not required to accept this License, since you have not 184 | signed it. However, nothing else grants you permission to modify or 185 | distribute the Program or its derivative works. These actions are 186 | prohibited by law if you do not accept this License. Therefore, by 187 | modifying or distributing the Program (or any work based on the 188 | Program), you indicate your acceptance of this License to do so, and 189 | all its terms and conditions for copying, distributing or modifying 190 | the Program or works based on it. 191 | 192 | 6. Each time you redistribute the Program (or any work based on the 193 | Program), the recipient automatically receives a license from the 194 | original licensor to copy, distribute or modify the Program subject to 195 | these terms and conditions. You may not impose any further 196 | restrictions on the recipients' exercise of the rights granted herein. 197 | You are not responsible for enforcing compliance by third parties to 198 | this License. 199 | 200 | 7. If, as a consequence of a court judgment or allegation of patent 201 | infringement or for any other reason (not limited to patent issues), 202 | conditions are imposed on you (whether by court order, agreement or 203 | otherwise) that contradict the conditions of this License, they do not 204 | excuse you from the conditions of this License. If you cannot 205 | distribute so as to satisfy simultaneously your obligations under this 206 | License and any other pertinent obligations, then as a consequence you 207 | may not distribute the Program at all. For example, if a patent 208 | license would not permit royalty-free redistribution of the Program by 209 | all those who receive copies directly or indirectly through you, then 210 | the only way you could satisfy both it and this License would be to 211 | refrain entirely from distribution of the Program. 212 | 213 | If any portion of this section is held invalid or unenforceable under 214 | any particular circumstance, the balance of the section is intended to 215 | apply and the section as a whole is intended to apply in other 216 | circumstances. 217 | 218 | It is not the purpose of this section to induce you to infringe any 219 | patents or other property right claims or to contest validity of any 220 | such claims; this section has the sole purpose of protecting the 221 | integrity of the free software distribution system, which is 222 | implemented by public license practices. Many people have made 223 | generous contributions to the wide range of software distributed 224 | through that system in reliance on consistent application of that 225 | system; it is up to the author/donor to decide if he or she is willing 226 | to distribute software through any other system and a licensee cannot 227 | impose that choice. 228 | 229 | This section is intended to make thoroughly clear what is believed to 230 | be a consequence of the rest of this License. 231 | 232 | 8. If the distribution and/or use of the Program is restricted in 233 | certain countries either by patents or by copyrighted interfaces, the 234 | original copyright holder who places the Program under this License 235 | may add an explicit geographical distribution limitation excluding 236 | those countries, so that distribution is permitted only in or among 237 | countries not thus excluded. In such case, this License incorporates 238 | the limitation as if written in the body of this License. 239 | 240 | 9. The Free Software Foundation may publish revised and/or new versions 241 | of the General Public License from time to time. Such new versions will 242 | be similar in spirit to the present version, but may differ in detail to 243 | address new problems or concerns. 244 | 245 | Each version is given a distinguishing version number. If the Program 246 | specifies a version number of this License which applies to it and "any 247 | later version", you have the option of following the terms and conditions 248 | either of that version or of any later version published by the Free 249 | Software Foundation. If the Program does not specify a version number of 250 | this License, you may choose any version ever published by the Free Software 251 | Foundation. 252 | 253 | 10. If you wish to incorporate parts of the Program into other free 254 | programs whose distribution conditions are different, write to the author 255 | to ask for permission. For software which is copyrighted by the Free 256 | Software Foundation, write to the Free Software Foundation; we sometimes 257 | make exceptions for this. Our decision will be guided by the two goals 258 | of preserving the free status of all derivatives of our free software and 259 | of promoting the sharing and reuse of software generally. 260 | 261 | NO WARRANTY 262 | 263 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 264 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 265 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 266 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 267 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 268 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 269 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 270 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 271 | REPAIR OR CORRECTION. 272 | 273 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 274 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 275 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 276 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 277 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 278 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 279 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 280 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 281 | POSSIBILITY OF SUCH DAMAGES. 282 | 283 | END OF TERMS AND CONDITIONS 284 | 285 | How to Apply These Terms to Your New Programs 286 | 287 | If you develop a new program, and you want it to be of the greatest 288 | possible use to the public, the best way to achieve this is to make it 289 | free software which everyone can redistribute and change under these terms. 290 | 291 | To do so, attach the following notices to the program. It is safest 292 | to attach them to the start of each source file to most effectively 293 | convey the exclusion of warranty; and each file should have at least 294 | the "copyright" line and a pointer to where the full notice is found. 295 | 296 | {description} 297 | Copyright (C) {year} {fullname} 298 | 299 | This program is free software; you can redistribute it and/or modify 300 | it under the terms of the GNU General Public License as published by 301 | the Free Software Foundation; either version 2 of the License, or 302 | (at your option) any later version. 303 | 304 | This program is distributed in the hope that it will be useful, 305 | but WITHOUT ANY WARRANTY; without even the implied warranty of 306 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 307 | GNU General Public License for more details. 308 | 309 | You should have received a copy of the GNU General Public License along 310 | with this program; if not, write to the Free Software Foundation, Inc., 311 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 312 | 313 | Also add information on how to contact you by electronic and paper mail. 314 | 315 | If the program is interactive, make it output a short notice like this 316 | when it starts in an interactive mode: 317 | 318 | Gnomovision version 69, Copyright (C) year name of author 319 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 320 | This is free software, and you are welcome to redistribute it 321 | under certain conditions; type `show c' for details. 322 | 323 | The hypothetical commands `show w' and `show c' should show the appropriate 324 | parts of the General Public License. Of course, the commands you use may 325 | be called something other than `show w' and `show c'; they could even be 326 | mouse-clicks or menu items--whatever suits your program. 327 | 328 | You should also get your employer (if you work as a programmer) or your 329 | school, if any, to sign a "copyright disclaimer" for the program, if 330 | necessary. Here is a sample; alter the names: 331 | 332 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 333 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 334 | 335 | {signature of Ty Coon}, 1 April 1989 336 | Ty Coon, President of Vice 337 | 338 | This General Public License does not permit incorporating your program into 339 | proprietary programs. If your program is a subroutine library, you may 340 | consider it more useful to permit linking proprietary applications with the 341 | library. If this is what you want to do, use the GNU Lesser General 342 | Public License instead of this License. 343 | -------------------------------------------------------------------------------- /DMD.m: -------------------------------------------------------------------------------- 1 | % DMD interface to the TI 6500 EVM DLP evaluation module 2 | % 3 | % Methods: 4 | % DMD Constructor, establishes communications 5 | % delete Destructor, closes connection 6 | % send Send data to the DMD 7 | % receive Receive data from the DMD 8 | % setMode 9 | % definePattern 10 | % numOfImages 11 | % initPatternLoad 12 | % uploadPattern 13 | % patternControl 14 | % getCount 15 | % testPattern 16 | % idle 17 | % active 18 | % reset 19 | % sleep Puts the DMD to sleep 20 | % wakeup Wakes up the DMD after a standby operation 21 | % fwversion Returns the firmware version of the DMD 22 | % 23 | % Example:: 24 | % d = DMD('debug', 1) 25 | % 26 | % This toolbox is based on the hidapi implementation written by Peter Corke 27 | % in the framework of his robotics toolbox. The original source code can be 28 | % found on http://www.petercorke.com/Robotics_Toolbox.html. 29 | % 30 | % Author: Klaus Hueck (e-mail: khueck (at) physik (dot) uni-hamburg (dot) de) 31 | % Version: 0.0.1alpha 32 | % Changes tracker: 28.01.2016 - First version 33 | % License: GPL v3 34 | 35 | classdef DMD < handle 36 | 37 | properties 38 | % connection handle 39 | conn; 40 | % debug input 41 | debug; 42 | % sequence counter, initialize to 1 43 | count = 1; 44 | % power status of the dmd, wide awake at init 45 | sleeping = 0; 46 | % DMD in idle mode? Is not idle at init 47 | isidle = 0; 48 | % is a pattern running? 49 | isrunning = 1; 50 | % display mode 51 | displayMode = 3; 52 | % contains the java frame for displaying images in fullscreen on 53 | % the dmd 54 | frame = ''; 55 | end 56 | 57 | methods 58 | function dmd = DMD(varargin) 59 | % DMD.DMD Create a DMD object 60 | % 61 | % d = DMD(OPTIONS) is an object that represents a connection 62 | % interface to a TI 6500 EVM DMD module. 63 | % 64 | % Options: 65 | % 'debug',D Debug level, show communications packet 66 | 67 | % make all helper functions known to DMD() 68 | libDir = strsplit(mfilename('fullpath'), filesep); 69 | % fix fullfile file separation for linux systems 70 | firstsep = ''; 71 | if (isunix == 1) 72 | firstsep = '/'; 73 | end 74 | addpath(fullfile(firstsep, libDir{1:end-1}, 'helperFunctions')); 75 | 76 | % init the properties 77 | opt.debug = 0; 78 | % read in the options 79 | opt = tb_optparse(opt, varargin); 80 | 81 | % connect via usb 82 | dmd.debug = opt.debug; 83 | if dmd.debug <= 1 84 | dmd.conn = usbDMDIO; 85 | elseif dmd.debug == 2 86 | dmd.conn = usbDMDIO(dmd.debug); 87 | elseif dmd.debug == 3 88 | disp('Dummy mode. Didn''t connect to DMD!'); 89 | end 90 | connect = 1; 91 | 92 | % error 93 | if(~connect) 94 | fprintf('Add error handling here!\n'); 95 | end 96 | end 97 | 98 | function delete(dmd) 99 | % DMD.delete Delete the DMD object 100 | % 101 | % delete(b) closes the connection to the dmd 102 | 103 | % wake it up before closing if it was asleep 104 | if dmd.sleeping 105 | dmd.wakeup; 106 | end 107 | 108 | % check if display mode is normal video mode. if so, shut down 109 | % the it6535 receiver 110 | if dmd.displayMode == 0 111 | % shut down it6535 receiver &0x1A01 112 | cmd = Command(); 113 | cmd.Mode = 'w'; % set to write mode 114 | cmd.Reply = true; % we want no reply 115 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 116 | data = dec2bin(0, 8); % usb payload 117 | cmd.addCommand({'0x1A', '0x01'}, data); % set the usb command 118 | dmd.send(cmd) 119 | dmd.receive; 120 | end 121 | dmd.conn.close(); 122 | end 123 | 124 | function send(dmd, cmd) 125 | % DMD.send Send data to the dmd 126 | % 127 | % DMD.send(cmd) sends a command to the dmd through the 128 | % connection handle. 129 | % 130 | % Notes:: 131 | % - cmd is a command object. 132 | % 133 | % Example:: 134 | % d.send(cmd) 135 | 136 | % make chunks of 64 byte and send via loop 137 | if ~(dmd.debug == 3) 138 | chunkSize = 64; 139 | numOfTransfers = ceil(length(cmd.msg)/chunkSize); 140 | for i = 1:numOfTransfers 141 | % add data to packet 142 | if i == numOfTransfers 143 | data = cmd.msg((i-1)*chunkSize+1:end); 144 | else 145 | data = cmd.msg((i-1)*chunkSize+1:i*chunkSize); 146 | end 147 | % send the message through the DMDIO write function 148 | dmd.conn.write(data); 149 | end 150 | end 151 | 152 | if dmd.debug > 0 153 | fprintf('sent: [ '); 154 | for ii=1:length(cmd.msg) 155 | fprintf('%s ',dec2hex(cmd.msg(ii))) 156 | end 157 | fprintf(']\n'); 158 | end 159 | end 160 | 161 | function display(dmd,I) 162 | %DMD.display supermethod to prepare, upload and show a matlab 163 | %matrix 164 | % 165 | % display prepares the matrix I for upload, uploads it and 166 | % finally displays it on the dmd 167 | % 168 | % Note: 169 | % - I is the input matrix (max size 1920x1080x1) 170 | % 171 | % Example:: 172 | % d.display(ones(1920,1080)) 173 | 174 | 175 | % check which display mode the dmd is in 176 | if dmd.displayMode == 0 177 | 178 | % check if source is locked 179 | [~, stat] = dmd.status; 180 | if stat(4) 181 | % show full screen image on dmd 182 | ind = findDMD(); 183 | if ~isempty(ind) 184 | fullscreen(I,ind); 185 | else 186 | warndlg(['There is no screen with the native DMD resolution available. ' ... 187 | 'Please connect the DMD, and select the proper display mode.']); 188 | end 189 | else 190 | disp('Video source not locked'); 191 | end 192 | elseif dmd.displayMode == 1 193 | disp('Displaying images via pre-stored pattern mode is not implemented yet'); 194 | elseif dmd.displayMode == 2 195 | 196 | disp('Displaying images via video pattern mode is not implemented yet'); 197 | 198 | elseif dmd.displayMode == 3 199 | % pattern on the fly mode -> use usb connection to transfer 200 | % images 201 | if dmd.debug 202 | disp('Display image in pattern on-the-fly mode'); 203 | end 204 | % prepare matrix for upload 205 | BMP = prepBMP(I); 206 | % set the mode to pattern display mode 207 | dmd.setMode 208 | % stop the running pattern 209 | dmd.patternControl(0) 210 | % define the pattern to be uploaded 211 | dmd.definePattern % FIXME: allow for better pattern definition 212 | % set the number of images to be uploaded to one 213 | dmd.numOfImages 214 | % initialize the pattern upload 215 | dmd.initPatternLoad(0,size(BMP,1)); 216 | % do the upload 217 | dmd.uploadPattern(BMP) 218 | % set the dmd state to play 219 | dmd.patternControl(2) 220 | end 221 | end 222 | 223 | function setMode(dmd,m) % 0x1A1B 224 | %DMD.setMode Sets DMD to the selected mode 225 | % 226 | % setMode puts the dmd to the selected mode. Possible modes m 227 | % are: 228 | % 0 = Normal video mode 229 | % 1 = Pre-stored pattern mode (Images from flash) 230 | % 2 = Video pattern mode 231 | % 3 = Pattern On-The-Fly mode (Images loaded through USB) 232 | % 233 | % Note: 234 | % - m is the mode. The default mode is 3. 235 | % 236 | % Example:: 237 | % d.setMode(2) 238 | 239 | if nargin == 1 240 | m = 3; 241 | if dmd.debug 242 | disp('setMode: Use default mode 3'); 243 | end 244 | elseif nargin > 2 245 | disp(['setMode: Please only specify the dmd to work on and ' ... 246 | 'the required operation mode']); 247 | end 248 | 249 | if any(m > 3) || any(m < 0) 250 | disp('setMode: Only modes [0-3] are allowed, use default mode 3.'); 251 | m = 3; 252 | end 253 | 254 | % make new display mode known the dmd object 255 | dmd.displayMode = m; 256 | 257 | cmd = Command(); 258 | cmd.Mode = 'w'; % set to write mode 259 | cmd.Reply = true; % we want no reply 260 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 261 | data = dec2bin(m, 8); % usb payload 262 | cmd.addCommand({'0x1A', '0x1B'}, data); % set the usb command 263 | dmd.send(cmd) 264 | dmd.receive; 265 | 266 | % set additional parameters depending on the chosen display 267 | % mode 268 | if dmd.displayMode == 0 || dmd.displayMode == 2 269 | % set it6535 receiver to display port &0x1A01 270 | cmd = Command(); 271 | cmd.Mode = 'w'; % set to write mode 272 | cmd.Reply = true; % we want no reply 273 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 274 | data = dec2bin(2, 8); % usb payload 275 | cmd.addCommand({'0x1A', '0x01'}, data); % set the usb command 276 | dmd.send(cmd) 277 | dmd.receive; 278 | dmd.display(zeros(1080,1920)); 279 | end 280 | end 281 | 282 | function definePattern(dmd) % 0x1A34 283 | %DMD.definePattern Defines the LUT entry for a pattern 284 | % 285 | % 286 | 287 | idx = 0; % pattern index 288 | exposureTime = 500000; % exposure time in �s 289 | clearAfter = 1; % clear pattern after exposure 290 | bitDepth = 1; % desired bit depth (1 corresponds to bitdepth of 1) 291 | leds = 1; % select which color to use 292 | triggerIn = 0; % wait for trigger or cuntinue 293 | darkTime = 0; % dark time after exposure in �s 294 | triggerOut = 0; % use trigger2 as output 295 | patternIdx = 0; % image pattern index 296 | bitPosition = 0; % bit position in image pattern 297 | 298 | % define commandstring bytewise as per the C900 Programmer's 299 | % guide 300 | data = char; 301 | data(1:2,:) = dec2bin(typecast(uint16(idx), 'uint8'),8); 302 | data(3:6,:) = dec2bin(typecast(uint32(exposureTime), 'uint8'),8); % needs to override byte 5 as there is no such thing as uint24 :-( 303 | data(6,:) = [dec2bin(triggerIn), dec2bin(leds,3), ... 304 | dec2bin(bitDepth-1,3), dec2bin(clearAfter)]; 305 | data(7:10,:) = dec2bin(typecast(uint32(darkTime), 'uint8'),8); % needs to override byte 9 as there is no such thing as uint24 :-( 306 | data(10,:) = dec2bin(typecast(uint8(triggerOut), 'uint8'),8); 307 | byte11_10 = [dec2bin(patternIdx,11) dec2bin(bitPosition,5)]; 308 | data(11:12,:) = [byte11_10(1:8); byte11_10(9:16)]; 309 | 310 | cmd = Command(); 311 | cmd.Mode = 'w'; % set to write mode 312 | cmd.Reply = true; % we want a reply! 313 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 314 | cmd.addCommand({'0x1A', '0x34'}, data); % set the usb command 315 | dmd.send(cmd) 316 | dmd.receive; 317 | end 318 | 319 | function numOfImages(dmd, n, m) % 0x1A31 320 | %DMD.numOfImages Sets the number of images in a pattern 321 | % 322 | % Note: 323 | % - n is the number if images in the pattern 324 | % - m is the number of times the pattern should be repeated 325 | 326 | if nargin == 1 327 | n = 1; 328 | m = 100; 329 | end 330 | 331 | data = ''; 332 | data(1:2,:) = dec2bin(typecast(uint16(n), 'uint8'),8); 333 | data(3:6,:) = dec2bin(typecast(uint32(m), 'uint8'),8); 334 | 335 | cmd = Command(); 336 | cmd.Mode = 'w'; % set to write mode 337 | cmd.Reply = true; % we want a reply! 338 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 339 | cmd.addCommand({'0x1A', '0x31'}, data); % set the usb command 340 | dmd.send(cmd) 341 | dmd.receive; 342 | 343 | end 344 | 345 | function initPatternLoad(dmd, idx, imgSize) % 0x1A2A 346 | %DMD.initPattern Initializes the BMP pattern load 347 | % 348 | 349 | data = ''; 350 | data(1:2,:) = dec2bin(typecast(uint16(idx), 'uint8'),8); 351 | data(3:6,:) = dec2bin(typecast(uint32(imgSize), 'uint8'),8); 352 | 353 | cmd = Command(); 354 | cmd.Mode = 'w'; % set to write mode 355 | cmd.Reply = true; % we want a reply! 356 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 357 | cmd.addCommand({'0x1A', '0x2A'}, data); % set the usb command 358 | dmd.send(cmd) 359 | dmd.receive; 360 | end 361 | 362 | function uploadPattern(dmd, BMP) % 0x1A2B 363 | %DMD.uploadPattern Uploads the prepared BMP to the dmd 364 | % 365 | 366 | % The C900 input buffer is 512 byte large. The HID buffer is 64 367 | % byte large and the command header of the first transmission 368 | % of each 512 byte chunk is 8 byte long. 369 | % Thus we need to split the data in chunks of 1x 55 byte plus 370 | % nx 64 byte until all 512 bytes of the input buffer are 371 | % filled. Then, we need to issue a new transmission with the 372 | % full 8 byte header. 373 | chunkSize = 54; 374 | numOfTransfers = ceil(size(BMP,1)/chunkSize); 375 | textprogressbar('Upload Image: '); 376 | for i = 1:numOfTransfers 377 | % add data to packet 378 | if i == numOfTransfers 379 | data = BMP((i-1)*chunkSize+1:end,:); 380 | else 381 | data = BMP((i-1)*chunkSize+1:i*chunkSize,:); 382 | end 383 | % get size of packet to be transfered 384 | numOfBytes = dec2bin(typecast(uint16(size(data,1)),'uint8'),8); 385 | data = [numOfBytes; dec2bin(hex2dec(data),8)]; %#ok 386 | cmd = Command(); 387 | cmd.Mode = 'w'; % set to write mode 388 | cmd.Reply = true; % we want a reply! 389 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 390 | cmd.addCommand({'0x1A', '0x2B'}, data); % set the usb command 391 | dmd.send(cmd); 392 | rmsg = dmd.receive; 393 | if ~(cmd.msg(2) == rmsg(2)) 394 | error('Transmission error sent and received message do not correspond!') 395 | end 396 | textprogressbar(100*i/numOfTransfers); 397 | end 398 | textprogressbar(' Done...'); 399 | end 400 | 401 | function patternControl(dmd, c) % 0x1A24 402 | %DMD.patternControl Starts, stops or pauses the actual pattern 403 | % 404 | % patternControl starts, stops or pauses the actual pattern. A 405 | % stop will cause the pattern to stop. The next start command 406 | % will restart the sequence from the beginning. A pause command 407 | % will stop the pattern while the next start command restarts 408 | % the sequence by re-displaying the current pattern in the 409 | % sequence. 410 | % 411 | % Note: 412 | % - c is the command and can be 413 | % 0 = Stop 414 | % 1 = Pause 415 | % 2 = Start 416 | % 417 | % Example:: 418 | % d.patternControl() 419 | 420 | cmd = Command(); 421 | cmd.Mode = 'w'; % set to write mode 422 | cmd.Reply = true; % we want a reply! 423 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 424 | data = dec2bin(c,8); % usb payload 425 | cmd.addCommand({'0x1A', '0x24'}, data); % set the usb command 426 | dmd.send(cmd); 427 | dmd.receive; 428 | end 429 | 430 | function c = getCount(dmd) 431 | % DMD.getCount Gets the actual value of the counter 432 | % 433 | % c = DMD.getCount(dmd) gets the actual value of the internal 434 | % counter for the sequence byte and increases it by one. If 435 | % dmd.count > 255 dmd.count will be reset to 1 436 | % 437 | % Example:: 438 | % c = d.getCount(); 439 | c = dmd.count; 440 | dmd.count = dmd.count + 1; 441 | dmd.count(dmd.count > 255) = 1; 442 | end 443 | 444 | function rmsg = receive(dmd) 445 | % DMD.receive Receive data from the dmd 446 | % 447 | % rmsg = DMD.receive() receives data from the dmd through 448 | % the connection handle. 449 | % 450 | % Example:: 451 | % rmsg = d.receive() 452 | 453 | % read the message through the DMDIO read function 454 | if ~(dmd.debug == 3) 455 | rmsg = dmd.conn.read(); 456 | if dmd.debug > 0 457 | fprintf('received: [ '); 458 | for ii=1:length(rmsg) 459 | fprintf('%d ',rmsg(ii)) 460 | end 461 | fprintf(']\n'); 462 | end 463 | else 464 | rmsg = zeros(20); 465 | end 466 | end 467 | 468 | function testPattern(dmd, p) 469 | % DMD.testpattern Show test pattern 470 | % 471 | % testpattern sets the input source of the dmd to the internal 472 | % test pattern generator and shows the selected test pattern 473 | % 474 | % Pattern Adresses: 475 | % 0 = Solid field 476 | % 1 = Horizontal ramp 477 | % 2 = Vertical ramp 478 | % 3 = Horizontal lines 479 | % 4 = Diagonal lines 480 | % 5 = Vertical lines 481 | % 6 = Grid 482 | % 7 = Checkerboard 483 | % 8 = RGB ramp 484 | % 9 = Color bars 485 | % 10 = Step bars 486 | % 487 | % Note: 488 | % - p is the adress of the pattern 489 | % 490 | % Example:: 491 | % d.testpattern(1) 492 | 493 | if ~dmd.sleeping 494 | cmd = Command(); 495 | cmd.Mode = 'w'; % set to write mode 496 | cmd.Reply = false; % we want a reply! 497 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 498 | data = '00000001'; % usb payload 499 | cmd.addCommand({'0x1A', '0x00'}, data); % set the usb command 500 | dmd.send(cmd) 501 | 502 | if p <= 10 503 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 504 | data = dec2bin(p,8); % usb payload 505 | cmd.addCommand({'0x12', '0x03'}, data); % set the usb command 506 | dmd.send(cmd) 507 | else 508 | disp(['The selected pattern does not exist. ' ... 509 | 'Valid pattern addresses are [0-10]']); 510 | end 511 | else 512 | if dmd.debug 513 | disp('The DMD is asleep! Do not disturb!'); 514 | end 515 | end 516 | 517 | end 518 | 519 | function idle(dmd) 520 | %DMD.idle Puts the DMD in idle mode 521 | % 522 | % idle puts the dmd to idle mode. 523 | % 524 | % Example:: 525 | % d.idle() 526 | 527 | if ~dmd.isidle 528 | cmd = Command(); 529 | cmd.Mode = 'w'; % set to write mode 530 | cmd.Reply = true; % we want a reply! 531 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 532 | data = '00000001'; % usb payload 533 | cmd.addCommand({'0x02', '0x01'}, data); % set the usb command 534 | dmd.send(cmd); 535 | dmd.receive; 536 | dmd.isidle = 1; 537 | else 538 | if dmd.debug 539 | disp('DMD is already in idle mode!'); 540 | end 541 | end 542 | end 543 | 544 | function active(dmd) 545 | %DMD.active Puts the DMD from idle back to active mode 546 | % 547 | % active puts the dmd back to active mode. 548 | % 549 | % Example:: 550 | % d.active() 551 | 552 | if dmd.isidle 553 | cmd = Command(); 554 | cmd.Mode = 'w'; % set to write mode 555 | cmd.Reply = true; % we want a reply! 556 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 557 | data = '00000000'; % usb payload 558 | cmd.addCommand({'0x02', '0x01'}, data); % set the usb command 559 | dmd.send(cmd) 560 | dmd.receive; 561 | dmd.isidle = 0; 562 | else 563 | if dmd.debug 564 | disp('DMD was already active!'); 565 | end 566 | end 567 | end 568 | 569 | function sleep(dmd) 570 | % DMD.sleep Put DMD to sleep 571 | % 572 | % sleep puts the dmd to stand by mode. 573 | % 574 | % Example:: 575 | % d.sleep() 576 | 577 | if ~dmd.sleeping 578 | cmd = Command(); 579 | cmd.Mode = 'w'; % set to write mode 580 | cmd.Reply = false; % we want a reply! 581 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 582 | data = '00000001'; % usb payload 583 | cmd.addCommand({'0x02', '0x00'}, data); % set the usb command 584 | dmd.send(cmd) 585 | dmd.sleeping = 1; 586 | else 587 | if dmd.debug 588 | disp('DMD is already sleeping! Sleeps now even deeper...'); 589 | end 590 | end 591 | end 592 | 593 | function reset(dmd) 594 | % DMD.reset Do a software reset 595 | % 596 | % reset does a software reset on the dmd. 597 | % 598 | % Example:: 599 | % d.reset() 600 | 601 | cmd = Command(); 602 | cmd.Mode = 'w'; % set to write mode 603 | cmd.Reply = false; % we want a reply! 604 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 605 | data = '00000010'; % usb payload 606 | cmd.addCommand({'0x02', '0x00'}, data); % set the usb command 607 | dmd.send(cmd) 608 | end 609 | 610 | function wakeup(dmd) 611 | % DMD.wakeup Wakeup DMD after sleep 612 | % 613 | % wakeup puts the dmd back to normal operation mode. 614 | % 615 | % Example:: 616 | % d.wakeup() 617 | 618 | if dmd.sleeping 619 | cmd = Command(); 620 | cmd.Mode = 'w'; % set to write mode 621 | cmd.Reply = false; % we want a reply! 622 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 623 | data = '00000000'; % usb payload 624 | cmd.addCommand({'0x02', '0x00'}, data); % set the usb command 625 | dmd.send(cmd) 626 | dmd.sleeping = 0; 627 | else 628 | if dmd.debug 629 | disp('DMD was not sleeping! Did''t wake it up...'); 630 | end 631 | end 632 | end 633 | 634 | function fwVersion(dmd) 635 | % DMD.fwversion Return firmware version 636 | % 637 | % fwversion returns firmware version. 638 | % 639 | % Example:: 640 | % d.fwversion() 641 | 642 | cmd = Command(); 643 | cmd.Mode = 'r'; % set to read mode 644 | cmd.Reply = true; % we want a reply! 645 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 646 | cmd.addCommand({'0x02', '0x05'}, ''); 647 | dmd.send(cmd); 648 | 649 | % receive the command 650 | msg = dmd.receive()'; 651 | 652 | % parse firmware version 653 | rpatch = typecast(uint8(msg(5:6)),'uint16'); 654 | rminor = uint8(msg(7)); 655 | rmajor = uint8(msg(8)); 656 | APIpatch = typecast(uint8(msg(9:10)),'uint16'); 657 | APIminor = uint8(msg(11)); 658 | APImajor = uint8(msg(12)); 659 | v = [num2str(rmajor) '.' num2str(rminor) '.' num2str(rpatch)]; 660 | 661 | % display the result 662 | disp(['I am a ' deblank(dmd.conn.handle.getProductString) ... 663 | '. My personal details are:']); 664 | disp([blanks(5) 'Application Software Version: v' v]); 665 | disp([blanks(5) 'API Software Version: ' num2str(APImajor) '.' ... 666 | num2str(APIminor) '.' num2str(APIpatch)]); 667 | disp(['If I don''t work complain to my manufacturer ' ... 668 | dmd.conn.handle.getManufacturersString]); 669 | end 670 | 671 | 672 | function hwstat = hwstatus(dmd) % 0x1A0A 673 | % DMD.hwstatus Returns the hardware status of the DMD 674 | % 675 | % hwstatus returns the hardware status of the dmd as described 676 | % in the DLPC900 programmers guide on page 15. 677 | % Meaning of the different bits see manual. 678 | % 679 | % Example:: 680 | % d.hwstatus() 681 | 682 | cmd = Command(); 683 | cmd.Mode = 'r'; % set to read mode 684 | cmd.Reply = true; % we want a reply! 685 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 686 | cmd.addCommand({'0x1A', '0x0A'}, ''); 687 | dmd.send(cmd); 688 | 689 | % receive the command 690 | msg = dmd.receive()'; 691 | 692 | % parse hardware status 693 | hwstat = dec2bin(msg(5),8); 694 | end 695 | 696 | function [stat, statbin] = status(dmd) % 0x1A0C 697 | % DMD.status Returns the main status of the DMD 698 | % 699 | % status returns the main status of the dmd as described 700 | % in the DLPC900 programmers guide on page 16. 701 | % The first output returns a cell array with a human readable 702 | % status message. The second one just returns the bits as 703 | % listed in the developer manual. 704 | % 705 | % Example:: 706 | % d.status() 707 | 708 | cmd = Command(); 709 | cmd.Mode = 'r'; % set to read mode 710 | cmd.Reply = true; % we want a reply! 711 | cmd.Sequence = dmd.getCount; % set the rolling counter of the sequence byte 712 | cmd.addCommand({'0x1A', '0x0C'}, ''); 713 | dmd.send(cmd); 714 | 715 | % receive the command 716 | msg = dmd.receive()'; 717 | 718 | % parse hardware status 719 | statbin = dec2bin(msg(5),8); 720 | statbin = str2num(fliplr(statbin(3:end))'); 721 | 722 | % 0 status 723 | stat0 = {'Mirrors not parked | '; ... 724 | 'Sequencer stopped | '; ... 725 | 'Video is running | '; ... 726 | 'External source not locked | '; ... 727 | 'Port 1 sync not valid | '; ... 728 | 'Port 2 sync not valid';}; 729 | % 1 status 730 | stat1 = {'Mirrors parked | '; ... 731 | 'Sequencer running | '; ... 732 | 'Video is frozen | '; ... 733 | 'External source locked | '; ... 734 | 'Port 1 sync valid | '; ... 735 | 'Port 2 sync valid';}; 736 | stat = stat0; 737 | stat(statbin == 1) = stat1(statbin == 1); 738 | end 739 | end 740 | end 741 | --------------------------------------------------------------------------------