From e66efbbe8df2dd4e7de0a1e9bd129cf92e00f92f Mon Sep 17 00:00:00 2001 From: vikle012 Date: Wed, 11 Sep 2019 13:57:14 +0200 Subject: Initializes repo. --- Kod/bilbana/IOFunctions/config_IOs.m | 191 ++++++++ Kod/bilbana/IOFunctions/get_car_position.m | 81 ++++ Kod/bilbana/IOFunctions/get_manual_speed.m | 279 +++++++++++ Kod/bilbana/IOFunctions/initialize_counters.m | 217 +++++++++ Kod/bilbana/IOFunctions/set_car_speed.m | 56 +++ Kod/bilbana/IOFunctions/start_race.m | 56 +++ Kod/bilbana/IOFunctions/terminate.m | 83 ++++ Kod/bilbana/run_scalectrix.m | 47 ++ Kod/bilbana/studentFunctions/car_controller.m | 16 + Kod/bilbana/studentFunctions/init_car.m | 25 + Kod/bilbana/studentFunctions/plot_results.m | 15 + Kod/bilbana/studentFunctions/run_simple_example.m | 41 ++ Kod/bilbana/studentFunctions/update_control.m | 16 + Kod/bilbana/studentFunctions/update_position.m | 39 ++ Kod/display/ClientServerApp/Client/Client.cpp | 151 ++++++ Kod/display/ClientServerApp/Client/Client.vcproj | 188 ++++++++ Kod/display/ClientServerApp/Client/Client.vcxproj | 165 +++++++ Kod/display/ClientServerApp/ClientServerApp.sln | 53 +++ Kod/display/ClientServerApp/ClientServerApp.suo | Bin 0 -> 25088 bytes Kod/display/ClientServerApp/Common/ComConduit.cpp | 151 ++++++ Kod/display/ClientServerApp/Common/ComConduit.h | 59 +++ Kod/display/ClientServerApp/Common/Common.vcproj | 203 ++++++++ Kod/display/ClientServerApp/Common/Common.vcxproj | 139 ++++++ Kod/display/ClientServerApp/Common/Conduit.cpp | 529 +++++++++++++++++++++ Kod/display/ClientServerApp/Common/Conduit.h | 145 ++++++ Kod/display/ClientServerApp/Common/ReadABuffer.cpp | 36 ++ Kod/display/ClientServerApp/Common/ReadABuffer.h | 20 + .../ClientServerApp/Common/WriteABuffer.cpp | 67 +++ Kod/display/ClientServerApp/Common/WriteABuffer.h | 22 + Kod/display/ClientServerApp/Common/ipclink.h | 80 ++++ Kod/display/ClientServerApp/Release/Client.exe | Bin 0 -> 10240 bytes Kod/display/ClientServerApp/Release/Server.exe | Bin 0 -> 13312 bytes .../ClientServerApp/Release/matlabclient.mexw32 | Bin 0 -> 12800 bytes .../ClientServerApp/Release/matlabclient.mexw64 | Bin 0 -> 14848 bytes .../ClientServerApp/Release/startServer.bat | 15 + Kod/display/ClientServerApp/Server/Server.cpp | 418 ++++++++++++++++ Kod/display/ClientServerApp/Server/Server.vcproj | 189 ++++++++ Kod/display/ClientServerApp/Server/Server.vcxproj | 167 +++++++ .../ClientServerApp/matlabClient/matlabClient.cpp | 400 ++++++++++++++++ .../matlabClient/matlabClient.vcproj | 178 +++++++ .../matlabClient/matlabClient.vcxproj | 158 ++++++ .../ClientServerApp/matlabClient/stdafx.cpp | 8 + Kod/display/ClientServerApp/matlabClient/stdafx.h | 15 + .../ClientServerApp/matlabClient/targetver.h | 13 + Kod/display/ClientServerApp/matlabMake.bat | 16 + Kod/display/DisplaySpec/edip320-8e.pdf | Bin 0 -> 1183861 bytes Kod/display/display_exempel.m | 161 +++++++ 47 files changed, 4908 insertions(+) create mode 100644 Kod/bilbana/IOFunctions/config_IOs.m create mode 100644 Kod/bilbana/IOFunctions/get_car_position.m create mode 100644 Kod/bilbana/IOFunctions/get_manual_speed.m create mode 100644 Kod/bilbana/IOFunctions/initialize_counters.m create mode 100644 Kod/bilbana/IOFunctions/set_car_speed.m create mode 100644 Kod/bilbana/IOFunctions/start_race.m create mode 100644 Kod/bilbana/IOFunctions/terminate.m create mode 100644 Kod/bilbana/run_scalectrix.m create mode 100644 Kod/bilbana/studentFunctions/car_controller.m create mode 100644 Kod/bilbana/studentFunctions/init_car.m create mode 100644 Kod/bilbana/studentFunctions/plot_results.m create mode 100644 Kod/bilbana/studentFunctions/run_simple_example.m create mode 100644 Kod/bilbana/studentFunctions/update_control.m create mode 100644 Kod/bilbana/studentFunctions/update_position.m create mode 100644 Kod/display/ClientServerApp/Client/Client.cpp create mode 100644 Kod/display/ClientServerApp/Client/Client.vcproj create mode 100644 Kod/display/ClientServerApp/Client/Client.vcxproj create mode 100644 Kod/display/ClientServerApp/ClientServerApp.sln create mode 100644 Kod/display/ClientServerApp/ClientServerApp.suo create mode 100644 Kod/display/ClientServerApp/Common/ComConduit.cpp create mode 100644 Kod/display/ClientServerApp/Common/ComConduit.h create mode 100644 Kod/display/ClientServerApp/Common/Common.vcproj create mode 100644 Kod/display/ClientServerApp/Common/Common.vcxproj create mode 100644 Kod/display/ClientServerApp/Common/Conduit.cpp create mode 100644 Kod/display/ClientServerApp/Common/Conduit.h create mode 100644 Kod/display/ClientServerApp/Common/ReadABuffer.cpp create mode 100644 Kod/display/ClientServerApp/Common/ReadABuffer.h create mode 100644 Kod/display/ClientServerApp/Common/WriteABuffer.cpp create mode 100644 Kod/display/ClientServerApp/Common/WriteABuffer.h create mode 100644 Kod/display/ClientServerApp/Common/ipclink.h create mode 100644 Kod/display/ClientServerApp/Release/Client.exe create mode 100644 Kod/display/ClientServerApp/Release/Server.exe create mode 100644 Kod/display/ClientServerApp/Release/matlabclient.mexw32 create mode 100644 Kod/display/ClientServerApp/Release/matlabclient.mexw64 create mode 100644 Kod/display/ClientServerApp/Release/startServer.bat create mode 100644 Kod/display/ClientServerApp/Server/Server.cpp create mode 100644 Kod/display/ClientServerApp/Server/Server.vcproj create mode 100644 Kod/display/ClientServerApp/Server/Server.vcxproj create mode 100644 Kod/display/ClientServerApp/matlabClient/matlabClient.cpp create mode 100644 Kod/display/ClientServerApp/matlabClient/matlabClient.vcproj create mode 100644 Kod/display/ClientServerApp/matlabClient/matlabClient.vcxproj create mode 100644 Kod/display/ClientServerApp/matlabClient/stdafx.cpp create mode 100644 Kod/display/ClientServerApp/matlabClient/stdafx.h create mode 100644 Kod/display/ClientServerApp/matlabClient/targetver.h create mode 100644 Kod/display/ClientServerApp/matlabMake.bat create mode 100644 Kod/display/DisplaySpec/edip320-8e.pdf create mode 100644 Kod/display/display_exempel.m (limited to 'Kod') diff --git a/Kod/bilbana/IOFunctions/config_IOs.m b/Kod/bilbana/IOFunctions/config_IOs.m new file mode 100644 index 0000000..0a84d2a --- /dev/null +++ b/Kod/bilbana/IOFunctions/config_IOs.m @@ -0,0 +1,191 @@ +function [] = config_IOs() +%cCONFIG_IOS Configurates the input and output digital channels +% +% Starts tasks for 5 digital channels, 3 output and 2 input channels. +% There is one channel per task. +% +% These channels corresponds to: +% +% Output channels: +% SCLK - Serial Clock Input. +% CS_INV - Active-Low Chip Select. Data will not be clocked into DIN +% unless CS is low. When CS is high, DOUT is high impedance. +% DIN - Digital Serial Input. Data is clocked in at the rising edge of +% SCLK. +% +% Input channels: +% SSTRB - Serial Strobe Output. In internal clock mode, SSTRB goes low +% when the MAX186/MAX188 begin the A/D conversion and goes high +% when the conversion is done. In external clock mode, SSTRB +% pulses high for one clock period before the MSB decision. High +% impedance when CS is high (external mode). +% DOUT - Serial Data Output. Data is clocked out at the falling edge of +% SCLK. High impedance when CS is high. +% +% These channels corresponds to pin 19 - 15 on the ADC MAXIM MAX186 chip. +% +% Tobias Lindell - 2013-02-12 + +global mytaskh +global lib + +DAQmx_Val_ChanPerLine =0; % One Channel For Each Line +DAQmx_Val_ChanForAllLines =1; %#ok % One Channel For All Lines + +if isempty(lib) + lib = 'myni'; % library alias + if ~libisloaded(lib) + disp('Matlab: Load nicaiu.dll') + funclist = loadlibrary('c:\windows\system32\nicaiu.dll','C:\Program Files (x86)\National Instruments\Shared\ExternalCompilerSupport\C\include\nidaqmx.h','alias',lib); %#ok + %if you do NOT have nicaiu.dll and nidaqmx.h + %in your Matlab path,add full pathnames or copy the files. + %libfunctions(lib,'-full') % use this to show the... + %libfunctionsview(lib) % included function + disp('Matlab: Nicaiu.dll loaded!') + end +end + +% DOlines = {'Dev1/port0/line0','Dev1/port0/line1','Dev1/port0/line2'}; +lineGrouping = DAQmx_Val_ChanPerLine; % One Channel For Each Line +mytaskh.DO_SCLK = DAQmxCreateDOChan(lib,'Dev1/port0/line0',lineGrouping); +mytaskh.DO_CS_INV = DAQmxCreateDOChan(lib,'Dev1/port0/line1',lineGrouping); +mytaskh.DO_DIN = DAQmxCreateDOChan(lib,'Dev1/port0/line2',lineGrouping); + +% DIlines = {'Dev1/port0/line3','Dev1/port0/line4'}; +mytaskh.DI_SSTRB = DAQmxCreateDIChan(lib,'Dev1/port0/line3',lineGrouping); +mytaskh.DI_DOUT = DAQmxCreateDIChan(lib,'Dev1/port0/line4',lineGrouping); + +end + +function taskh = DAQmxCreateDIChan(lib,lines,lineGrouping) +% function taskh = DAQmxCreateDIChan(lib,lines,lineGrouping) +% +% this function creates a task and adds digital output line(s) to the task +% +% inputs: +% lib - .dll or alias (ex. 'myni') +% lines - line(s) to add to task +% 1 line example: 'Dev1/port0/line0' +% 2 lines example: {'Dev1/port0/line0','Dev1/port0/line1'} +% passing as .../line0-1 probably also works, but I didn't test +% lineGrouping - either DAQmx_Val_ChanPerLine or DAQmx_Val_ChanForAllLines +% +% +% C functions used: +% int32 DAQmxCreateTask (const char taskName[],TaskHandle *taskHandle); +% int32 DAQmxCreateDIChan (TaskHandle taskHandle,const char lines[],const char nameToAssignToLines[],int32 lineGrouping); +% int32 DAQmxTaskControl (TaskHandle taskHandle,int32 action); +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + + +% create task +taskh = []; +name_task = ''; % recommended to avoid problems +[err,~,taskh] = calllib(lib,'DAQmxCreateTask',name_task,uint32(taskh)); +DAQmxCheckError(lib,err); + +% % check whether done +% [err,b,istaskdone] = calllib(lib,'DAQmxIsTaskDone',(taskh),0); +% DAQmxCheckError(lib,err); + +% create DI channel(s) and add to task +% numchan = numel(lines); +name_line = ''; % recommended to avoid problems +if ~iscell(lines) % just 1 channel + [err,~,~,~] = calllib(lib,'DAQmxCreateDIChan',taskh,lines,name_line,lineGrouping); + DAQmxCheckError(lib,err); +else % more than 1 channel to add to task + for m = 1:numel(lines) % loop to add channels + [err,~,~,~] = calllib(lib,'DAQmxCreateDIChan',taskh,lines{m},name_line,lineGrouping); + DAQmxCheckError(lib,err); + end +end + +% verify everything OK +DAQmx_Val_Task_Verify =2; % Verify +[err,~] = calllib(lib,'DAQmxTaskControl',taskh,DAQmx_Val_Task_Verify); +DAQmxCheckError(lib,err); +end + +function taskh = DAQmxCreateDOChan(lib,lines,lineGrouping) +% function taskh = DAQmxCreateDOChan(lib,lines,lineGrouping) +% +% this function creates a task and adds digital output line(s) to the task +% +% inputs: +% lib - .dll or alias (ex. 'myni') +% lines - line(s) to add to task +% 1 line example: 'Dev1/port0/line0' +% 2 lines example: {'Dev1/port0/line0','Dev1/port0/line1'} +% passing as .../line0-1 probably also works, but I didn't test +% lineGrouping - either DAQmx_Val_ChanPerLine or DAQmx_Val_ChanForAllLines +% +% +% C functions used: +% int32 DAQmxCreateTask (const char taskName[],TaskHandle *taskHandle); +% int32 DAQmxCreateDOChan (TaskHandle taskHandle,const char lines[],const char nameToAssignToLines[],int32 lineGrouping); +% int32 DAQmxTaskControl (TaskHandle taskHandle,int32 action); +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + + +% create task +taskh = []; +name_task = ''; % recommended to avoid problems +[err,~,taskh] = calllib(lib,'DAQmxCreateTask',name_task,uint32(taskh)); +DAQmxCheckError(lib,err); + +% % check whether done +% [err,b,istaskdone] = calllib(lib,'DAQmxIsTaskDone',(taskh),0); +% DAQmxCheckError(lib,err); + +% create DO channel(s) and add to task +name_line = ''; % recommended to avoid problems +if ~iscell(lines) + [err,~,~,~] = calllib(lib,'DAQmxCreateDOChan',taskh,lines,name_line,lineGrouping); + DAQmxCheckError(lib,err); +else % more than 1 channel to add to task + for m = 1:numel(lines) + [err,~,~,~] = calllib(lib,'DAQmxCreateDOChan',taskh,lines{m},name_line,lineGrouping); + DAQmxCheckError(lib,err); + end +end + +% verify everything OK +DAQmx_Val_Task_Verify = 2; % Verify +[err,~] = calllib(lib,'DAQmxTaskControl',taskh,DAQmx_Val_Task_Verify); +DAQmxCheckError(lib,err); +end + +function DAQmxCheckError(lib,err) +% function DAQmxCheckError(lib,err) +% +% read error code +% zero means no error - does nothing +% nonzero - find out error string and generate error +% +% inputs: +% lib = .dll or alias (ex. 'myni') +% err = DAQmx error +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + +if err ~= 0 + % find out how long the error string is + [numerr,~] = calllib(lib,'DAQmxGetErrorString',err,'',0); + + % get error string + errstr = char(1:numerr); % have to pass dummy string of correct length + [~,errstr] = calllib(lib,'DAQmxGetErrorString',err,errstr,numerr); + + % matlab error + error(['DAQmx error - ',errstr]) +end +end \ No newline at end of file diff --git a/Kod/bilbana/IOFunctions/get_car_position.m b/Kod/bilbana/IOFunctions/get_car_position.m new file mode 100644 index 0000000..ef68fc2 --- /dev/null +++ b/Kod/bilbana/IOFunctions/get_car_position.m @@ -0,0 +1,81 @@ +function [add_lap,add_check_point,elapsed_time_check_point] = get_car_position(track) +%GET_CAR_POSITION Reads the current values of the lap and check point +%counters, and resets them if they are not equal to zero. +% +% Tobias Lindell 2013-02-13 + +global mytaskh +global lib + +switch nargin + case 1 + add_lap = []; + add_check_point = []; + elapsed_time_check_point = []; + + if isempty(mytaskh) + disp(['User needs to initialize counters for track ',num2str(track),' before getting car position!']) + clearvars -global mytaskh lib + return + end + + switch track + case 1 + if isfield(mytaskh,'ctr_1') + add_check_point = DAQmxReadCounterScalarU32(lib,mytaskh.ctr_1); + add_lap = DAQmxReadCounterScalarU32(lib,mytaskh.ctr_2); + read_ticks = DAQmxReadCounterScalarU32(lib,mytaskh.ctr_3); + else + disp(['User needs to initialize counters for track ',num2str(track),' before getting car position!']) + return + end + case 2 + if isfield(mytaskh,'ctr_5') + add_check_point = DAQmxReadCounterScalarU32(lib,mytaskh.ctr_5); + add_lap = DAQmxReadCounterScalarU32(lib,mytaskh.ctr_6); + read_ticks = DAQmxReadCounterScalarU32(lib,mytaskh.ctr_7); + else + disp(['User needs to initialize counters for track ',num2str(track),' before getting car position!']) + return + end + + otherwise + disp('Wrong track number sent to get_car_position!') + return + end + + if add_check_point || add_lap + elapsed_time_check_point = read_ticks / 100; + start_race(track); + clear read_ticks + end + otherwise + disp('Wrong number of input arguments sent to get_car_position(track)! Should be 1!') +end +end + +function Data = DAQmxReadCounterScalarU32(lib,taskh) +% function taskh = DAQmxReadCounterScalarU32(lib,taskh) +% +% this function reads a counter value from previously setup task +% +% inputs: +% lib - .dll or alias (ex. 'myni') +% taskh - taskhandle of analog inputs +% +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + +DAQmx_Val_WaitInfinitely = -1.0; + +reserved = []; +reserved_ptr = libpointer('uint32Ptr',reserved); +Data = 1; +data_ptr = libpointer('uint32Ptr',Data); +calllib(lib,'DAQmxReadCounterScalarU32',taskh,DAQmx_Val_WaitInfinitely,data_ptr,reserved_ptr); +counter = get(data_ptr); +Data = counter.Value; +end + diff --git a/Kod/bilbana/IOFunctions/get_manual_speed.m b/Kod/bilbana/IOFunctions/get_manual_speed.m new file mode 100644 index 0000000..04af0ae --- /dev/null +++ b/Kod/bilbana/IOFunctions/get_manual_speed.m @@ -0,0 +1,279 @@ +function [manual_speed] = get_manual_speed(track) +%GET_MANUAL_SPEED Reads input from gas handle and returns converted value. +% Uses digital in/out functions to get and set values on the channels set +% up by the function config_IOs. +% +% Output channels: +% SCLK - Serial Clock Input. +% CS_INV - Active-Low Chip Select. Data will not be clocked into DIN +% unless CS is low. When CS is high, DOUT is high impedance. +% DIN - Digital Serial Input. Data is clocked in at the rising edge of +% SCLK. +% +% Input channels: +% SSTRB - Serial Strobe Output. In internal clock mode, SSTRB goes low +% when the MAX186/MAX188 begin the A/D conversion and goes high +% when the conversion is done. In external clock mode, SSTRB +% pulses high for one clock period before the MSB decision. High +% impedance when CS is high (external mode). +% DOUT - Serial Data Output. Data is clocked out at the falling edge of +% SCLK. High impedance when CS is high. +% +% User needs to manually clock the serial clock of the analog/digital +% converter to read or write data. +% +% Tobias Lindell - 2013-02-12 + +global mytaskh +global lib + +switch nargin + case 1 + manual_speed = []; + + if isempty(mytaskh) + disp('User needs to initialize IO before getting manual car speed!') + clearvars -global mytaskh lib + return + else + if ~isfield(mytaskh,'DO_SCLK') + disp('User needs to initialize IO before getting manual car speed!') + return + end + end + + switch track + case 1 + control_bit = 0; + case 2 + control_bit = 1; + otherwise + disp('Wrong track number sent to get_manual_speed!') + return + end + + % Channels: + % mytaskh.DO_SCLK + % mytaskh.DO_CS_INV + % mytaskh.DO_DIN + % mytaskh.DI_SSTRB + % mytaskh.DI_DOUT + + DAQmx_Val_ChanPerLine =0; %#ok<*NASGU> % One Channel For Each Line + DAQmx_Val_ChanForAllLines =1; % One Channel For All Lines + DAQmx_Val_GroupByChannel = 0; % Group by Channel + DAQmx_Val_GroupByScanNumber =1; % Group by Scan Number + + numSampsPerChan = 1; + timeout = 1; + fillMode = DAQmx_Val_GroupByChannel; % Group by Channel + % fillMode = DAQmx_Val_GroupByScanNumber; % Group by Scan Number + dataLayout = DAQmx_Val_GroupByChannel; % Group by Channel + % dataLayout = DAQmx_Val_GroupByScanNumber; % Group by Scan Number + numchanDI = 1; % DI lines + numsample = 1; + + + + % Setup outports + DAQmxWriteDigitalLines(lib,mytaskh.DO_CS_INV,... + numSampsPerChan,timeout,dataLayout,1); + DAQmxWriteDigitalLines(lib,mytaskh.DO_SCLK,... + numSampsPerChan,timeout,dataLayout,0); + DAQmxWriteDigitalLines(lib,mytaskh.DO_DIN,... + numSampsPerChan,timeout,dataLayout,0); + DAQmxWriteDigitalLines(lib,mytaskh.DO_CS_INV,... + numSampsPerChan,timeout,dataLayout,0); + + % Send controll byte : "100x1110", där x är kontrollbiten. + set_ADC_bit(1); + set_ADC_bit(0); + set_ADC_bit(0); + set_ADC_bit(control_bit); + set_ADC_bit(1); + set_ADC_bit(1); + set_ADC_bit(1); + set_ADC_bit(0); + + pause(0.005) + + DAQmxWriteDigitalLines(lib,mytaskh.DO_SCLK,... + numSampsPerChan,timeout,dataLayout,1); + + ADC = zeros(1,12); + for i=1:12 + ADC(13-i) = get_ADC_bit(); + end + get_ADC_bit(); + get_ADC_bit(); + get_ADC_bit(); + get_ADC_bit(); + DAQmxWriteDigitalLines(lib,mytaskh.DO_CS_INV,... + numSampsPerChan,timeout,dataLayout,1); + + x1=ADC(12)*128+ADC(11)*64+ADC(10)*32+ADC(9)*16+ADC(8)*8+ADC(7)*4+ADC(6)*2+ADC(5)*1-128; + manual_speed = min(max(x1,0),127); + otherwise + disp('Wrong number of arguments sent to get_manual_speed(track)! Should be 1!'); +end +end + +function [] = set_ADC_bit(valueDO) +global mytaskh +global lib + +DAQmx_Val_ChanPerLine =0; % One Channel For Each Line +DAQmx_Val_ChanForAllLines =1; % One Channel For All Lines +DAQmx_Val_GroupByChannel = 0; % Group by Channel +DAQmx_Val_GroupByScanNumber =1; % Group by Scan Number + +numSampsPerChan = 1; +timeout = 1; +dataLayout = DAQmx_Val_GroupByChannel; % Group by Channel +% dataLayout = DAQmx_Val_GroupByScanNumber; % Group by Scan Number + +DAQmxWriteDigitalLines(lib,mytaskh.DO_DIN,... + numSampsPerChan,timeout,dataLayout,valueDO); + +DAQmxWriteDigitalLines(lib,mytaskh.DO_SCLK,... + numSampsPerChan,timeout,dataLayout,1); +DAQmxWriteDigitalLines(lib,mytaskh.DO_SCLK,... + numSampsPerChan,timeout,dataLayout,0); +end + +function [valueDI] = get_ADC_bit() +global mytaskh +global lib + +DAQmx_Val_ChanPerLine =0; % One Channel For Each Line +DAQmx_Val_ChanForAllLines =1; % One Channel For All Lines +DAQmx_Val_GroupByChannel = 0; % Group by Channel +DAQmx_Val_GroupByScanNumber =1; % Group by Scan Number + +numSampsPerChan = 1; +timeout = 1; +fillMode = DAQmx_Val_GroupByChannel; % Group by Channel +% fillMode = DAQmx_Val_GroupByScanNumber; % Group by Scan Number +dataLayout = DAQmx_Val_GroupByChannel; % Group by Channel +% dataLayout = DAQmx_Val_GroupByScanNumber; % Group by Scan Number +numchanDI = 1; % DI lines +numsample = 1; + +DAQmxWriteDigitalLines(lib,mytaskh.DO_SCLK,... + numSampsPerChan,timeout,dataLayout,0); +DAQmxWriteDigitalLines(lib,mytaskh.DO_SCLK,... + numSampsPerChan,timeout,dataLayout,1); +valueDI = DAQmxReadDigitalLines(lib,mytaskh.DI_DOUT,numSampsPerChan,timeout,fillMode,numchanDI,numsample); +end + +function sampsPerChanWritten = DAQmxWriteDigitalLines(lib,taskh,numSampsPerChan,timeout,dataLayout,DOvalue) +% function sampsPerChanWritten = DAQmxWriteDigitalLines(lib,taskh,numSampsPerChan,timeout,dataLayout,DOvalue) +% +% this function writes digital outputs from previously setup task +% +% inputs: +% lib - .dll or alias (ex. 'myni') +% taskh - taskhandle of analog inputs +% numSampsPerChan = ? +% timeout - in seconds +% dataLayout - DAQmx_Val_GroupByChannel or DAQmx_Val_GroupByScanNumber +% DOvalue - value to write (0 or 1) +% 1 channel example: 0 +% 2 channel example: [0,0] +% +% C functions: +% int32 DAQmxReadDigitalLines ( +% TaskHandle taskHandle,int32 numSampsPerChan,float64 timeout,bool32 fillMode, +% uInt8 readArray[],uInt32 arraySizeInBytes,int32 *sampsPerChanRead,int32 *numBytesPerSamp,bool32 *reserved); +% int32 DAQmxStopTask (TaskHandle taskHandle); +% int32 DAQmxWriteDigitalLines ( +% TaskHandle taskHandle,int32 numSampsPerChan,bool32 autoStart,float64 timeout,bool32 dataLayout, +% uInt8 writeArray[],int32 *sampsPerChanWritten,bool32 *reserved); +% int32 DAQmxStopTask (TaskHandle taskHandle); +% +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + +autoStart = 1; + + +[err,sampsPerChanWritten,empty] = calllib(lib,'DAQmxWriteDigitalLines',... + taskh,numSampsPerChan,autoStart,timeout,dataLayout,... + DOvalue,0,[]); +DAQmxCheckError(lib,err); +end + +function data = DAQmxReadDigitalLines(lib,taskh,numSampsPerChan,timeout,fillMode,numchan,numsample) +% function data = DAQmxReadDigitalLines(lib,taskh,numSampsPerChan,timeout,fillMode,numchan,numsample) +% +% this function reads digital inputs from previously setup task +% +% inputs: +% lib - .dll or alias (ex. 'myni') +% taskh - taskhandle of analog inputs +% numSampsPerChan = ? +% timeout - in seconds +% fillMode - DAQmx_Val_GroupByChannel or DAQmx_Val_GroupByScanNumber +% numchan - number of digital channels to read +% numsample - number of samples to read +% +% C functions: +% int32 DAQmxReadDigitalLines ( +% TaskHandle taskHandle,int32 numSampsPerChan,float64 timeout,bool32 fillMode, +% uInt8 readArray[],uInt32 arraySizeInBytes,int32 *sampsPerChanRead,int32 *numBytesPerSamp,bool32 *reserved); +% int32 DAQmxStopTask (TaskHandle taskHandle); +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + + +% make some pointers +% readarray1=ones(numchan,numsample); readarray1_ptr=libpointer('doublePtr',readarray1); +readarray1=ones(numchan,numsample); readarray1_ptr=libpointer('uint8Ptr',readarray1); +sampread=1; sampread_ptr=libpointer('int32Ptr',sampread); +bytespersamp=1; bytespersamp_ptr=libpointer('int32Ptr',bytespersamp); +empty=[]; empty_ptr=libpointer('uint32Ptr',empty); + +arraylength=numsample*numchan; % more like 'buffersize' + +[err,~,sampread,~,empty]=calllib(lib,'DAQmxReadDigitalLines',... + taskh,numSampsPerChan,timeout,fillMode,... + readarray1_ptr,arraylength,sampread_ptr,bytespersamp_ptr,empty_ptr); +DAQmxCheckError(lib,err); + +% err = calllib(lib,'DAQmxStopTask',taskh); +% DAQmxCheckError(lib,err); + +data = sampread; +end + +function DAQmxCheckError(lib,err) +% function DAQmxCheckError(lib,err) +% +% read error code +% zero means no error - does nothing +% nonzero - find out error string and generate error +% +% inputs: +% lib = .dll or alias (ex. 'myni') +% err = DAQmx error +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + +if err ~= 0 + % find out how long the error string is + [numerr,~] = calllib(lib,'DAQmxGetErrorString',err,'',0); + + % get error string + errstr = char(1:numerr); % have to pass dummy string of correct length + [~,errstr] = calllib(lib,'DAQmxGetErrorString',err,errstr,numerr); + + % matlab error + error(['DAQmx error - ',errstr]) +end +end \ No newline at end of file diff --git a/Kod/bilbana/IOFunctions/initialize_counters.m b/Kod/bilbana/IOFunctions/initialize_counters.m new file mode 100644 index 0000000..27e76ac --- /dev/null +++ b/Kod/bilbana/IOFunctions/initialize_counters.m @@ -0,0 +1,217 @@ +function [] = initialize_counters(track) +%INITIALIZE_COUNTERS Creates counter tasks by calling the new driver NIDAQmx. +% +% There are one task associated with each counter. The handles of these +% tasks are stored in global struct mytaskh. The tasks are not started +% by this function, the user needs to call set_car_speed and/or +% start_race to arm any counters. +% +% Track 1/track 2: +% ctr_0/ctr_4 - Pulse train signal, representing car speed. +% ctr_1/ctr_5 - Check point counter. +% ctr_2/ctr_6 - Lap counter. +% ctr_3/ctr_7 - Time counter, counts at 100kHz. +% +% Tobias Lindell - 2013-02-12 + +global mytaskh +global lib + +switch nargin + case 1 + lib = 'myni'; % library alias + if ~libisloaded(lib) + disp('Matlab: Loading nicaiu.dll. Please wait!') + funclist = loadlibrary('c:\windows\system32\nicaiu.dll','C:\Program Files (x86)\National Instruments\Shared\ExternalCompilerSupport\C\include\nidaqmx.h','alias',lib); %#ok + %if you do NOT have nicaiu.dll and nidaqmx.h + %in your Matlab path,add full pathnames or copy the files. + %libfunctions(lib,'-full') % use this to show the... + %libfunctionsview(lib) % included function + disp('Matlab: Nicaiu.dll loaded!') + end + + disp(['Initializing track ',num2str(track),' please wait!']) + + %%% NIconstants + DAQmx_Val_Hz = 10373; % Hz + + % DAQmx_Val_High = 10192; % High + DAQmx_Val_Low = 10214; % Low + + % DAQmx_Val_FiniteSamps = 10178; % Finite Samples + DAQmx_Val_ContSamps = 10123; % Continuous Samples + % DAQmx_Val_HWTimedSinglePoint = 12522; % Hardware Timed Single Point + + DAQmx_Val_Rising = 10280; % Rising + % DAQmx_Val_Falling = 10171; % Falling + + DAQmx_Val_CountUp = 10128; % Count Up + % DAQmx_Val_CountDown = 10124; % Count Down + % DAQmx_Val_ExtControlled = 10326; % Externally Controlled + + + + % Track 1 + switch track + case 1 + %%% Car speed counter + mytaskh.ctr_0 = DAQmxCreateCOPulseChanFreq(lib,'Dev1/ctr0',DAQmx_Val_Hz,DAQmx_Val_Low,2.5e-08,100,0.001); + calllib(lib,'DAQmxCfgImplicitTiming',mytaskh.ctr_0,DAQmx_Val_ContSamps,1000); + + %%% Sensor counters + + % Check points + % Starting count edges counter, detecting rising edges + mytaskh.ctr_1 = DAQmxCreateCICountEdgesChan(lib,'Dev1/ctr1',DAQmx_Val_Rising,DAQmx_Val_CountUp); + % Setting up terminal and filter + calllib(lib,'DAQmxSetCICountEdgesTerm',mytaskh.ctr_1,'Dev1/ctr1','PFI35'); + calllib(lib,'DAQmxSetCICountEdgesDigFltrEnable',mytaskh.ctr_1,'Dev1/ctr1',1); + calllib(lib,'DAQmxSetCICountEdgesDigFltrMinPulseWidth',mytaskh.ctr_1,'Dev1/ctr1',5e-6); + + % Lap counter + mytaskh.ctr_2 = DAQmxCreateCICountEdgesChan(lib,'Dev1/ctr2',DAQmx_Val_Rising,DAQmx_Val_CountUp); + calllib(lib,'DAQmxSetCICountEdgesTerm',mytaskh.ctr_2,'Dev1/ctr2','PFI31'); + calllib(lib,'DAQmxSetCICountEdgesDigFltrEnable',mytaskh.ctr_2,'Dev1/ctr2',1); + calllib(lib,'DAQmxSetCICountEdgesDigFltrMinPulseWidth',mytaskh.ctr_2,'Dev1/ctr2',5e-6); + + %%% Timer counter + mytaskh.ctr_3 = DAQmxCreateCICountEdgesChan(lib,'Dev1/ctr3',DAQmx_Val_Rising,DAQmx_Val_CountUp); + calllib(lib,'DAQmxSetCICountEdgesTerm',mytaskh.ctr_3,'Dev1/ctr3','/Dev1/100kHzTimebase'); + + case 2 + %%% Car speed counter + mytaskh.ctr_4 = DAQmxCreateCOPulseChanFreq(lib,'Dev1/ctr4',DAQmx_Val_Hz,DAQmx_Val_Low,2.5e-08,100,0.001); + calllib(lib,'DAQmxCfgImplicitTiming',mytaskh.ctr_4,DAQmx_Val_ContSamps,1000); + + %%% Sensor counters + % Check points + mytaskh.ctr_5 = DAQmxCreateCICountEdgesChan(lib,'Dev1/ctr5',DAQmx_Val_Rising,DAQmx_Val_CountUp); + calllib(lib,'DAQmxSetCICountEdgesTerm',mytaskh.ctr_5,'Dev1/ctr5','PFI19'); + calllib(lib,'DAQmxSetCICountEdgesDigFltrEnable',mytaskh.ctr_5,'Dev1/ctr5',1); + calllib(lib,'DAQmxSetCICountEdgesDigFltrMinPulseWidth',mytaskh.ctr_5,'Dev1/ctr5',5e-6); + + % Lap counter + mytaskh.ctr_6 = DAQmxCreateCICountEdgesChan(lib,'Dev1/ctr6',DAQmx_Val_Rising,DAQmx_Val_CountUp); + calllib(lib,'DAQmxSetCICountEdgesTerm',mytaskh.ctr_6,'Dev1/ctr6','PFI15'); + calllib(lib,'DAQmxSetCICountEdgesDigFltrEnable',mytaskh.ctr_6,'Dev1/ctr6',1); + calllib(lib,'DAQmxSetCICountEdgesDigFltrMinPulseWidth',mytaskh.ctr_6,'Dev1/ctr6',5e-6); + + %%% Timer counter + mytaskh.ctr_7 = DAQmxCreateCICountEdgesChan(lib,'Dev1/ctr7',DAQmx_Val_Rising,DAQmx_Val_CountUp); + calllib(lib,'DAQmxSetCICountEdgesTerm',mytaskh.ctr_7,'Dev1/ctr7','/Dev1/100kHzTimebase'); + + otherwise + disp('Wrong track number sent to initialize_counters!') + return + end + disp(['Track ',num2str(track),' initialized!']) + otherwise + disp('Wrong number of input arguments sent to initialize_counters(track)! Should be 1!') +end +end + +function DAQmxCheckError(lib,err) +% function DAQmxCheckError(lib,err) +% +% read error code +% zero means no error - does nothing +% nonzero - find out error string and generate error +% +% inputs: +% lib = .dll or alias (ex. 'myni') +% err = DAQmx error +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + +if err ~= 0 + % find out how long the error string is + [numerr,~] = calllib(lib,'DAQmxGetErrorString',err,'',0); + + % get error string + errstr = char(1:numerr); % have to pass dummy string of correct length + [~,errstr] = calllib(lib,'DAQmxGetErrorString',err,errstr,numerr); + + % matlab error + error(['DAQmx error - ',errstr]) +end +end + +function taskh = DAQmxCreateCICountEdgesChan(lib,ctrs,edge,direction) +% function taskh = DAQmxCreateCICountEdgesChan(lib,ctrs,edge,direction) +% +% this function creates a task and adds counter input channel(s) to the task +% +% inputs: +% lib - .dll or alias (ex. 'myni') +% ctrs - channel(s) to add to task +% 1 channel example: 'Dev1/ctr0' +% 2 channels example: {'Dev1/ctr0','Dev1/ctr1'} +% passing as .../ctr0-1 probably also works, but I didn't test +% edge - which edge that is detected/counted ('rising' or 'falling') +% direction - direction to count ('increment' or 'decrement') +% +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + +taskh = []; +name_task = ''; % recommended to avoid problems +[err,~,taskh] = calllib(lib,'DAQmxCreateTask',name_task,uint32(taskh)); +DAQmxCheckError(lib,err); + +name_line = ''; % recommended to avoid problems +[err,~,~,~] = calllib(lib,'DAQmxCreateCICountEdgesChan',taskh,ctrs,name_line,edge,0,direction); +DAQmxCheckError(lib,err); + +% verify everything OK +DAQmx_Val_Task_Verify = 2; % Verify +[err,~] = calllib(lib,'DAQmxTaskControl',taskh,DAQmx_Val_Task_Verify); +DAQmxCheckError(lib,err); + +end + +function taskh = DAQmxCreateCOPulseChanFreq(lib,ctrs,units,idleState,initialDelay,freq,dutyCycle) +% function taskh = DAQmxCreateCOPulseChanFreq(lib,ctrs,units,idleState,initialDelay,freq,dutyCycle) +% +% this function creates a task and adds counter input channel(s) to the task +% +% inputs: +% lib - .dll or alias (ex. 'myni') +% ctrs - channel(s) to add to task +% 1 channel example: 'Dev1/ctr0' +% 2 channels example: {'Dev1/ctr0','Dev1/ctr1'} +% passing as .../ctr0-1 probably also works, but I didn't test +% units - The units in which to specify freq. (DAQmx_Val_Hz = hertz) +% idleState - The resting state of the output terminal. +% DAQmx_Val_High - High state. +% DAQmx_Val_Low - Low state. +% initialDelay - The amount of time in seconds to wait before generating the first pulse. +% freq - The frequency at which to generate pulses. +% dutyCycle - The width of the pulse divided by the pulse period. +% +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + + +taskh = []; +name_task = ''; % recommended to avoid problems +[err,~,taskh] = calllib(lib,'DAQmxCreateTask',name_task,uint32(taskh)); +DAQmxCheckError(lib,err); + +name_line = ''; % recommended to avoid problems +[err,~,~,~] = calllib(lib,'DAQmxCreateCOPulseChanFreq',taskh,ctrs,name_line,units,idleState,initialDelay,freq,dutyCycle); +DAQmxCheckError(lib,err); + +% verify everything OK +DAQmx_Val_Task_Verify = 2; % Verify +[err,~] = calllib(lib,'DAQmxTaskControl',taskh,DAQmx_Val_Task_Verify); +DAQmxCheckError(lib,err); + +end + + diff --git a/Kod/bilbana/IOFunctions/set_car_speed.m b/Kod/bilbana/IOFunctions/set_car_speed.m new file mode 100644 index 0000000..3aab1db --- /dev/null +++ b/Kod/bilbana/IOFunctions/set_car_speed.m @@ -0,0 +1,56 @@ +function [] = set_car_speed(track,speed) +%SET_CAR_SPEED Sets the specified car (track) to a specified speed. +% Changes the duty cycle of counter 0 and 4 to change speed of car on +% track 1 and track 2 respectively. Valid values of the duty cycle are +% between 0 and 1, the input speed of the cars are defined as percent. +% +% Tobias Lindell 2013-02-12. + +global mytaskh +global lib + +switch nargin + case 2 + % Check if _any_ counters been initilized, stop program if not + if isempty(mytaskh) + disp(['User needs to initialize counters for track ',num2str(track),' before setting car speed!']) + clearvars -global mytaskh lib + return + end + + % Setting duty cycle, with limits + speed = min(99, speed); + speed = max(0.1,speed); + duty_cycle = speed / 100; + + switch track + case 1 + % Check if track 1 counter has been initialized, stop program if not + if isfield(mytaskh,'ctr_0') + % Stop task (necessary to change duty cycle) + calllib(lib,'DAQmxStopTask',mytaskh.ctr_0); + % Set new duty cycle + calllib(lib,'DAQmxSetCOPulseDutyCyc',mytaskh.ctr_0,'Dev1/ctr0',duty_cycle); + % Restart task + calllib(lib,'DAQmxStartTask',mytaskh.ctr_0); + else + disp(['User needs to initialize counters for track ',num2str(track),' before setting car speed!']) + return + end + case 2 + if isfield(mytaskh,'ctr_4') + calllib(lib,'DAQmxStopTask',mytaskh.ctr_4); + calllib(lib,'DAQmxSetCOPulseDutyCyc',mytaskh.ctr_4,'Dev1/ctr4',duty_cycle); + calllib(lib,'DAQmxStartTask',mytaskh.ctr_4); + else + disp(['User needs to initialize counters for track ',num2str(track),' before setting car speed!']) + return + end + otherwise + disp('Wrong track number sent to set_car_speed!') + return + end + otherwise + disp('Wrong number of arguments sent to set_car_speed(track,speed)! Should be 2!') +end +end diff --git a/Kod/bilbana/IOFunctions/start_race.m b/Kod/bilbana/IOFunctions/start_race.m new file mode 100644 index 0000000..5e51017 --- /dev/null +++ b/Kod/bilbana/IOFunctions/start_race.m @@ -0,0 +1,56 @@ +function [] = start_race(track) +%START_RACE Stops, resets and starts all counters associated with specified +%track. +% All counters, except the pulse train speed counters, associated with a +% specified track are stopped and restarted. This resets the current +% values of the counters to the initial value (0 for all counters). +% +% At first call the counters just starts, the extra stopping of counters +% that are not running does nothing. +% +% Tobias Lindell - 2013-02-12 + +global mytaskh +global lib + +switch nargin + case 1 + % Check if _any_ counters been initilized, stop program if not + if isempty(mytaskh) + disp(['User needs to initialize counters for track ',num2str(track),' before setting car speed!']) + clearvars -global mytaskh lib + return + end + + switch track + case 1 + if ~isfield(mytaskh,'ctr_1') + disp(['User needs to initialize counters for track ',num2str(track),' before setting car speed!']) + return + end + calllib(lib,'DAQmxStopTask',mytaskh.ctr_1); + calllib(lib,'DAQmxStopTask',mytaskh.ctr_2); + calllib(lib,'DAQmxStopTask',mytaskh.ctr_3); + calllib(lib,'DAQmxStartTask',mytaskh.ctr_1); + calllib(lib,'DAQmxStartTask',mytaskh.ctr_2); + calllib(lib,'DAQmxStartTask',mytaskh.ctr_3); + case 2 + if ~isfield(mytaskh,'ctr_5') + disp(['User needs to initialize counters for track ',num2str(track),' before setting car speed!']) + return + end + calllib(lib,'DAQmxStopTask',mytaskh.ctr_5); + calllib(lib,'DAQmxStopTask',mytaskh.ctr_6); + calllib(lib,'DAQmxStopTask',mytaskh.ctr_7); + calllib(lib,'DAQmxStartTask',mytaskh.ctr_5); + calllib(lib,'DAQmxStartTask',mytaskh.ctr_6); + calllib(lib,'DAQmxStartTask',mytaskh.ctr_7); + otherwise + disp('Wrong track number sent to start_race!') + return + end + otherwise + disp('Wrong number of arguments sent to start_race(track)! Should be 1!') +end +end + diff --git a/Kod/bilbana/IOFunctions/terminate.m b/Kod/bilbana/IOFunctions/terminate.m new file mode 100644 index 0000000..26a43f2 --- /dev/null +++ b/Kod/bilbana/IOFunctions/terminate.m @@ -0,0 +1,83 @@ +function [] = terminate(track) +%TERMINATE Stops all counters associated with specified track. +% Stops all counters associated with a specified track, and clears the +% resources. +% +% If both tracks are terminated as a result of a call on terminate() all +% resources, including the global variables, will be cleared and the +% PCI6602 card will be reset to original state. +% +% Tobias Lindell 2013-02-12 + +global mytaskh +global lib + +switch nargin + case 1 + if isempty(mytaskh) + disp('User needs to initialize counters before terminating!') + clearvars -global mytaskh lib + return + end + + + switch track + case 1 + % Check if track 1 counter has been initialized, stop program if not + if isfield(mytaskh,'ctr_0') + % Clear counters of selcted track + calllib(lib,'DAQmxClearTask',mytaskh.ctr_0); + calllib(lib,'DAQmxClearTask',mytaskh.ctr_1); + calllib(lib,'DAQmxClearTask',mytaskh.ctr_2); + calllib(lib,'DAQmxClearTask',mytaskh.ctr_3); + clear mytaskh.ctr_0 + clear mytaskh.ctr_1 + clear mytaskh.ctr_2 + clear mytaskh.ctr_3 + mytaskh = rmfield(mytaskh,'ctr_0'); + mytaskh = rmfield(mytaskh,'ctr_1'); + mytaskh = rmfield(mytaskh,'ctr_2'); + mytaskh = rmfield(mytaskh,'ctr_3'); + % Check to see if counters of other track are cleared, if so + % reset card to original state and clear global variables + if ~isfield(mytaskh,'ctr_4') + disp('Everything terminated. Device will reset!') + calllib(lib,'DAQmxResetDevice','Dev1'); + clearvars -global mytaskh lib + end + + else + disp(['User needs to initialize counters for track ',num2str(track),' before terminating!']) + return + end + case 2 + if isfield(mytaskh,'ctr_4') + calllib(lib,'DAQmxClearTask',mytaskh.ctr_4); + calllib(lib,'DAQmxClearTask',mytaskh.ctr_5); + calllib(lib,'DAQmxClearTask',mytaskh.ctr_6); + calllib(lib,'DAQmxClearTask',mytaskh.ctr_7); + clear mytaskh.ctr_4 + clear mytaskh.ctr_5 + clear mytaskh.ctr_6 + clear mytaskh.ctr_7 + mytaskh = rmfield(mytaskh,'ctr_4'); + mytaskh = rmfield(mytaskh,'ctr_5'); + mytaskh = rmfield(mytaskh,'ctr_6'); + mytaskh = rmfield(mytaskh,'ctr_7'); + if ~isfield(mytaskh,'ctr_0') + disp('Everything terminated. Device will reset!') + calllib(lib,'DAQmxResetDevice','Dev1'); + clearvars -global mytaskh lib + end + else + disp(['User needs to initialize counters for track ',num2str(track),' before terminating!']) + return + end + otherwise + disp('Wrong track argument sent to terminate(track)! Should be 1 or 2!') + end + otherwise + disp('Wrong number of arguments sent to terminate(track)! Should be 1!') +end +end + diff --git a/Kod/bilbana/run_scalectrix.m b/Kod/bilbana/run_scalectrix.m new file mode 100644 index 0000000..8ef6f47 --- /dev/null +++ b/Kod/bilbana/run_scalectrix.m @@ -0,0 +1,47 @@ +function [] = run_scalectrix() +% Runs the Scalectrix with hand controls enabled. "q" stops execution. +% +% Tobias Lindell - 2013-02-12 + + +disp('Startar bilbanan. Avsluta med q') +hf=figure('position',[0 0 eps eps],'menubar','none'); + +%% Init race track +initialize_counters(1) +initialize_counters(2) + +config_IOs + +start_race(1) +start_race(2) + +%% Running loop +while 1 +% tic + % Check if user has pressed q + if strcmp(get(hf,'currentcharacter'),'q') + close(hf) + break + end + % force the event queue to flush + figure(hf) + drawnow + + % Read speed from controllers and set new car speeds + my_speed_1 = get_manual_speed(1); + my_speed_1 = 100*((55 - my_speed_1)/55); + set_car_speed(1,my_speed_1); + + my_speed_2 = get_manual_speed(2); + my_speed_2 = 100*((55 - my_speed_2)/55); + set_car_speed(2,my_speed_2) +% toc + pause(0.1) % Pause 0.1 s +end + +[lap_car1,chk_pnt_car1,time] = get_car_position(1) +[lap_car2,chk_pnt_car2,time] = get_car_position(2) + +terminate(1) +terminate(2) \ No newline at end of file diff --git a/Kod/bilbana/studentFunctions/car_controller.m b/Kod/bilbana/studentFunctions/car_controller.m new file mode 100644 index 0000000..069e8f5 --- /dev/null +++ b/Kod/bilbana/studentFunctions/car_controller.m @@ -0,0 +1,16 @@ +function car = car_controller(car_in) + +car = car_in; + +% Read sensors +[car, cp_passed] = update_position(car); + +if cp_passed + % Update speed + + new_control = car.control(end) + 0.5*(rand() - 0.5); % Temporary control policy + + car = update_control(new_control, car); +end + +end \ No newline at end of file diff --git a/Kod/bilbana/studentFunctions/init_car.m b/Kod/bilbana/studentFunctions/init_car.m new file mode 100644 index 0000000..8206206 --- /dev/null +++ b/Kod/bilbana/studentFunctions/init_car.m @@ -0,0 +1,25 @@ +function car = init_car(track_number) + +car = struct(); + +% Car state +car.state = 'intro'; + +% Track number +car.track_number = track_number; + +% Current track segment +car.position = 0; + +% Current lap +car.lap = 0; + +% Start race timer +car.t0 = tic(); + +% Control signal +car.control = nan(1,1); +car.control_log_time = nan(1,1); +car.control_log_position = zeros(1,1); + +end \ No newline at end of file diff --git a/Kod/bilbana/studentFunctions/plot_results.m b/Kod/bilbana/studentFunctions/plot_results.m new file mode 100644 index 0000000..34ea2e4 --- /dev/null +++ b/Kod/bilbana/studentFunctions/plot_results.m @@ -0,0 +1,15 @@ +% Plot the results +figure(100) +subplot(2,1,1) +stairs(car.control_log_time, car.control, 'LineWidth', 2) % Gör en trappstegsplot +xlabel('Time [s]') +ylabel('Control signal [%]') +title('Control signal trajectory') +grid on + +subplot(2,1,2) +stairs(car.control_log_time, car.control_log_position, 'r', 'LineWidth', 2) +xlabel('Time [s]') +ylabel('Car position [segment number]') +title('Car position') +grid on diff --git a/Kod/bilbana/studentFunctions/run_simple_example.m b/Kod/bilbana/studentFunctions/run_simple_example.m new file mode 100644 index 0000000..45794f0 --- /dev/null +++ b/Kod/bilbana/studentFunctions/run_simple_example.m @@ -0,0 +1,41 @@ +%% ---------------- Do not touch ---------------- % +disp('Startar bilbanan. Avsluta med q') +hf=figure('position',[0 0 eps eps],'menubar','none'); +% ----------------------------------------------- % +%% User input +track_number = 1; +car = init_car(track_number); + +%% Init race track +initialize_counters(car.track_number) +config_IOs +start_race(car.track_number) + +%% Start cars +start_control = 29; % 29 works for the white castrol car marked with number 82 +car = update_control(start_control, car); + +%% Running loop +while 1 + + % ---------------- Do not touch ---------------- % + % Check if user has pressed q + if strcmp(get(hf,'currentcharacter'),'q') + close(hf) + break + end + % force the event queue to flush + figure(hf) + drawnow + % ---------------------------------------------- % + + car = car_controller(car); + + pause(0.1) % Pause 0.1 s +end + +terminate(1) +terminate(2) + +% run file to plot results +plot_results(); \ No newline at end of file diff --git a/Kod/bilbana/studentFunctions/update_control.m b/Kod/bilbana/studentFunctions/update_control.m new file mode 100644 index 0000000..ee6599c --- /dev/null +++ b/Kod/bilbana/studentFunctions/update_control.m @@ -0,0 +1,16 @@ +function car = update_control(new_control_signal, car_in) + +% Return track struct +car = car_in; + +% Update track struct +car.control(end+1) = new_control_signal; +car.control_log_time(end+1) = toc(car.t0); +car.control_log_position(end+1) = car.position; + +% Update speed +set_car_speed(car.track_number, car.control(end)); + +end + + diff --git a/Kod/bilbana/studentFunctions/update_position.m b/Kod/bilbana/studentFunctions/update_position.m new file mode 100644 index 0000000..dfca55f --- /dev/null +++ b/Kod/bilbana/studentFunctions/update_position.m @@ -0,0 +1,39 @@ +function [car, gateway_passed] = update_position(car_in) + +car = car_in; + +[lap_car, chk_pnt, time] = get_car_position(car.track_number); + +if lap_car == true + % New lap + + % Update position on track + car.position = 1; + + % Add lap to lap counter + car.lap = car.lap + 1; + + % Update gw passed + gateway_passed = true; + + % Make sound + beep; + +elseif chk_pnt == true && car.position ~= 0 + % CP passed + + % Update position + car.position = car.position + 1; + + % update gw passed + gateway_passed = true; + + % Make sound + beep; + +else + gateway_passed = false; + +end + +end \ No newline at end of file diff --git a/Kod/display/ClientServerApp/Client/Client.cpp b/Kod/display/ClientServerApp/Client/Client.cpp new file mode 100644 index 0000000..efd08fe --- /dev/null +++ b/Kod/display/ClientServerApp/Client/Client.cpp @@ -0,0 +1,151 @@ +//============================================================================ +// Name : Client.cpp +// Author : Erik Hellström, hellstrom@isy.liu.se, 2008-12-14 +// Modified : Emil Larsson, lime@isy.liu.se, 2012-01-13 +// +// Description : The client requests data to be sent by the server. +// +//============================================================================ + +#include +#include +#include "ComConduit.h" + +// +// Show the command-line usage +// +void Usage(char* argv[]) { + + printf("\nUsage: %s \n\n",argv[0]); + printf(" -S= Send message, ex -S=\"hello world\".\n"); + printf(" -X Shutdown server.\n"); + printf("\n\n"); +} + + + + + +// +// Module main function +// +int main(int argc, char* argv[]) { + + // Conduit object + ComConduit Link; + // Key + KeyType key[KEY_LEN] = COM_KEY; + // Work variables + wchar_t data[COMSTR_LEN]; + bool doShutdown; + FlagType ret; + int i,j; + char c,*ptr; + WaitResult wr; + + // Initialize data + data[0] = '\0'; + doShutdown = false; + + // + // Parse the command-line. + // + for (i=1; i= COMSTR_LEN) { + fprintf(stderr,"\nToo long message.\n"); + return EXIT_FAIL; + } + data[j] = '\0'; + break; + + case 'X': + case 'x': + // Shutdown + doShutdown = true; + break; + } + } + + // Check valid args + if(!doShutdown && data[0] == '\0') { + Usage(argv); + return EXIT_FAIL; + } + + // + // Start client + // + if(!Link.StartClient(key)) { + fprintf(stderr,"StartClient() failed.\n"); + return EXIT_FAIL; + } + + ret = EXIT_OK; + if(doShutdown) { + // Tell server to shutdown + if(!Link.CauseShutdown()) { + fprintf(stderr,"\nCauseShutdown() failed.\n"); + ret = EXIT_FAIL; + } + } + else { + do { + // Check if server is ready + wr = Link.WaitForEvent(COM_READY,0); + if(wr != WAIT_OK) { + fprintf(stderr,"Server is not ready.\n"); + ret = EXIT_FAIL; + break; + } + + // Set data in shm + if(!Link.SetData(data)) { + fprintf(stderr,"SetData() failed.\n"); + ret = EXIT_FAIL; + break; + } + + // Request that the server send the data + if(!Link.CauseEvent(COM_REQUEST)) { + fprintf(stderr,"CauseEvent() failed.\n"); + ret = EXIT_FAIL; + break; + } + } while(false); + } + + // + // Shutdown + // + if(!Link.Shutdown()) { + fprintf(stderr,"Shutdown() failed.\n"); + ret = EXIT_FAIL; + } + if(ret == EXIT_OK) + fprintf(stdout, "\nClean exit.\n"); + + return ret; +} + diff --git a/Kod/display/ClientServerApp/Client/Client.vcproj b/Kod/display/ClientServerApp/Client/Client.vcproj new file mode 100644 index 0000000..dce2a22 --- /dev/null +++ b/Kod/display/ClientServerApp/Client/Client.vcproj @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Kod/display/ClientServerApp/Client/Client.vcxproj b/Kod/display/ClientServerApp/Client/Client.vcxproj new file mode 100644 index 0000000..7847220 --- /dev/null +++ b/Kod/display/ClientServerApp/Client/Client.vcxproj @@ -0,0 +1,165 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {3941DB40-83AA-41FD-A225-29B47EEFD704} + Client + Win32Proj + + + + Application + Unicode + true + + + Application + Unicode + true + + + Application + Unicode + + + Application + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + $(Configuration)\ + true + true + $(SolutionDir)$(Configuration)\ + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + $(Configuration)\ + false + false + + + + Disabled + ..\Common;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + EditAndContinue + + + true + Console + MachineX86 + + + + + Disabled + ..\Common;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + ProgramDatabase + + + true + Console + + + + + MaxSpeed + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + "..\Common";%(AdditionalIncludeDirectories) + + + true + Console + true + true + MachineX86 + + + + + MaxSpeed + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + "..\Common";%(AdditionalIncludeDirectories) + + + true + Console + true + true + + + + + + + + {8c1e78f5-0564-498a-958d-37a997bbfe49} + false + + + + + + \ No newline at end of file diff --git a/Kod/display/ClientServerApp/ClientServerApp.sln b/Kod/display/ClientServerApp/ClientServerApp.sln new file mode 100644 index 0000000..f23f502 --- /dev/null +++ b/Kod/display/ClientServerApp/ClientServerApp.sln @@ -0,0 +1,53 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Server", "Server\Server.vcxproj", "{7B05F65E-9D5F-49CE-9339-959759F4E98C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Client", "Client\Client.vcxproj", "{3941DB40-83AA-41FD-A225-29B47EEFD704}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common", "Common\Common.vcxproj", "{8C1E78F5-0564-498A-958D-37A997BBFE49}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "matlabClient", "matlabClient\matlabClient.vcxproj", "{3094F281-B0A8-4B46-B1CC-A4B8B5CC596A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7B05F65E-9D5F-49CE-9339-959759F4E98C}.Debug|Win32.ActiveCfg = Debug|Win32 + {7B05F65E-9D5F-49CE-9339-959759F4E98C}.Debug|Win32.Build.0 = Debug|Win32 + {7B05F65E-9D5F-49CE-9339-959759F4E98C}.Debug|x64.ActiveCfg = Debug|Win32 + {7B05F65E-9D5F-49CE-9339-959759F4E98C}.Release|Win32.ActiveCfg = Release|Win32 + {7B05F65E-9D5F-49CE-9339-959759F4E98C}.Release|Win32.Build.0 = Release|Win32 + {7B05F65E-9D5F-49CE-9339-959759F4E98C}.Release|x64.ActiveCfg = Release|x64 + {7B05F65E-9D5F-49CE-9339-959759F4E98C}.Release|x64.Build.0 = Release|x64 + {3941DB40-83AA-41FD-A225-29B47EEFD704}.Debug|Win32.ActiveCfg = Debug|Win32 + {3941DB40-83AA-41FD-A225-29B47EEFD704}.Debug|Win32.Build.0 = Debug|Win32 + {3941DB40-83AA-41FD-A225-29B47EEFD704}.Debug|x64.ActiveCfg = Debug|x64 + {3941DB40-83AA-41FD-A225-29B47EEFD704}.Debug|x64.Build.0 = Debug|x64 + {3941DB40-83AA-41FD-A225-29B47EEFD704}.Release|Win32.ActiveCfg = Release|Win32 + {3941DB40-83AA-41FD-A225-29B47EEFD704}.Release|Win32.Build.0 = Release|Win32 + {3941DB40-83AA-41FD-A225-29B47EEFD704}.Release|x64.ActiveCfg = Release|x64 + {3941DB40-83AA-41FD-A225-29B47EEFD704}.Release|x64.Build.0 = Release|x64 + {8C1E78F5-0564-498A-958D-37A997BBFE49}.Debug|Win32.ActiveCfg = Debug|Win32 + {8C1E78F5-0564-498A-958D-37A997BBFE49}.Debug|Win32.Build.0 = Debug|Win32 + {8C1E78F5-0564-498A-958D-37A997BBFE49}.Debug|x64.ActiveCfg = Debug|Win32 + {8C1E78F5-0564-498A-958D-37A997BBFE49}.Release|Win32.ActiveCfg = Release|Win32 + {8C1E78F5-0564-498A-958D-37A997BBFE49}.Release|Win32.Build.0 = Release|Win32 + {8C1E78F5-0564-498A-958D-37A997BBFE49}.Release|x64.ActiveCfg = Release|x64 + {8C1E78F5-0564-498A-958D-37A997BBFE49}.Release|x64.Build.0 = Release|x64 + {3094F281-B0A8-4B46-B1CC-A4B8B5CC596A}.Debug|Win32.ActiveCfg = Debug|Win32 + {3094F281-B0A8-4B46-B1CC-A4B8B5CC596A}.Debug|Win32.Build.0 = Debug|Win32 + {3094F281-B0A8-4B46-B1CC-A4B8B5CC596A}.Debug|x64.ActiveCfg = Debug|Win32 + {3094F281-B0A8-4B46-B1CC-A4B8B5CC596A}.Release|Win32.ActiveCfg = Release|Win32 + {3094F281-B0A8-4B46-B1CC-A4B8B5CC596A}.Release|Win32.Build.0 = Release|Win32 + {3094F281-B0A8-4B46-B1CC-A4B8B5CC596A}.Release|x64.ActiveCfg = Release|x64 + {3094F281-B0A8-4B46-B1CC-A4B8B5CC596A}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Kod/display/ClientServerApp/ClientServerApp.suo b/Kod/display/ClientServerApp/ClientServerApp.suo new file mode 100644 index 0000000..3de3b49 Binary files /dev/null and b/Kod/display/ClientServerApp/ClientServerApp.suo differ diff --git a/Kod/display/ClientServerApp/Common/ComConduit.cpp b/Kod/display/ClientServerApp/Common/ComConduit.cpp new file mode 100644 index 0000000..1bb952f --- /dev/null +++ b/Kod/display/ClientServerApp/Common/ComConduit.cpp @@ -0,0 +1,151 @@ +/* + * ComConduit.cpp + * + * Definition of the ComConduit class + * + * Author: Erik Hellström, hellstrom@isy.liu.se, 2008-12-14 + * Modified: Emil Larsson, lime@isy.liu.se, 2012-01-13 + */ + +#include "ComConduit.h" +#include +//#include "mex.h" + +// Constructor +ComConduit::ComConduit() { + + ptrData = NULL; +} + +// Destructor +ComConduit::~ComConduit() { + + // Issue shutdown function + Shutdown(); +} + +// Detach and remove shared memory segment +bool ComConduit::Shutdown() { + + if(Conduit::Shutdown()) { + ptrData = NULL; + return true; + } + else + return false; +} + +// Server initialization +bool ComConduit::StartServer(KeyType* key) { + + if(!Conduit::StartServer(key)) + return false; + + ptrData = (COMdata*)ptrShm; + ptrData->Common.Flag = NULL_FLAG; + ptrData->Common.DoShutdown = false; + ptrData->string[0] = '\0'; + + return true; +} + +// Client initialization +bool ComConduit::StartClient(KeyType* key) { + + if(!Conduit::StartClient(key)) + return false; + + ptrData = (COMdata*)ptrShm; + + return true; +} + +// Get shared data size +int ComConduit::GetDataSize() const { + + return sizeof(COMdata); +} + +// Get pointer to common shared data +CommonData* ComConduit::GetCommonData() const { + + if(ptrData == NULL) + return(NULL); + else + return(&ptrData->Common); +} + +// Get number of events +int ComConduit::GetNumEvents() const { + + return COM_NEVENTS; +} + +// Set the data +bool ComConduit::SetData(const wchar_t* data) { + + int ii; + + if(ptrData == NULL) + return false; + + // Request lock + if(!RequestLock()) + return false; + + // Copy string +// wcscpy_s(ptrData->string,COMSTR_LEN, data); + + /* Copy the wchar_t-string manual */ + for (ii=0; iistring[ii] = data[ii]; + // printf("\nptrData->string[%d]: %d \n", ii, ptrData->string[ii]); + } + /* Stop with a "null" char */ + ptrData->string[ii] = '\0'; + + // Release lock + if(!ReleaseLock()) + return false; + + return true; +} + +// Get the data +bool ComConduit::GetData(wchar_t* data) { + + int ii; + + if(ptrData == NULL) + return false; + + // Request lock + if(!RequestLock()) + return false; + + // Copy string +// wcscpy_s(data,COMSTR_LEN,ptrData->string); +// strcpy((char*) data, ptrData->string); + + //printf("\tComConduit:GetData: %d\n",ptrData->string[1]); + + /* Copy the wchar_t-string manual */ + for (ii=0; iistring[1]+EXTRA_LEN; ii++) + { + data[ii] = ptrData->string[ii]; + //printf("\nGetData:data[%d]: %d \n", ii, data[ii]); + } + /* Stop with a "null" char */ + data[ii] = (wchar_t) '\0'; + //printf("\nGetData:data[%d]: %d \n", ii, data[ii]); + + // Release lock + if(!ReleaseLock()) + return false; + + return true; +} + + + diff --git a/Kod/display/ClientServerApp/Common/ComConduit.h b/Kod/display/ClientServerApp/Common/ComConduit.h new file mode 100644 index 0000000..3948355 --- /dev/null +++ b/Kod/display/ClientServerApp/Common/ComConduit.h @@ -0,0 +1,59 @@ +/* + * ComConduit.h + * + * Declaration of the ComConduit class + * + * Author: Erik Hellström, hellstrom@isy.liu.se, 2008-12-14 + * Modified: Emil Larsson, lime@isy.liu.se, 2012-01-13 + */ + +#ifndef COMCONDUIT_H_ +#define COMCONDUIT_H_ + +// Include conduit base class +#include "Conduit.h" +// Include ipc interface +#include "ipclink.h" + +#include +// +// The ComConduit class +// +class ComConduit : public Conduit { + +public: + + // Construct & Destruct + ComConduit(); + virtual ~ComConduit(); + + // Server initialization + bool StartServer(KeyType* key); + // Client initialization + bool StartClient(KeyType* key); + // Detach and remove shared memory segment + bool Shutdown(); + + // Get shared data size + int GetDataSize() const; + // Get number of events + int GetNumEvents() const; + // Get pointer to common shared data + CommonData* GetCommonData() const; + + // Write data + bool SetData(const wchar_t* data); + + // Data read + bool GetData(wchar_t* data); + +private: + + // Pointer to shared data + COMdata* ptrData; + +}; + + + +#endif /* COMCONDUIT_H_ */ diff --git a/Kod/display/ClientServerApp/Common/Common.vcproj b/Kod/display/ClientServerApp/Common/Common.vcproj new file mode 100644 index 0000000..b5be92d --- /dev/null +++ b/Kod/display/ClientServerApp/Common/Common.vcproj @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Kod/display/ClientServerApp/Common/Common.vcxproj b/Kod/display/ClientServerApp/Common/Common.vcxproj new file mode 100644 index 0000000..be80a98 --- /dev/null +++ b/Kod/display/ClientServerApp/Common/Common.vcxproj @@ -0,0 +1,139 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {8C1E78F5-0564-498A-958D-37A997BBFE49} + Common + + + + StaticLibrary + MultiByte + true + + + StaticLibrary + MultiByte + true + + + StaticLibrary + NotSet + + + StaticLibrary + NotSet + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + $(Configuration)\ + $(SolutionDir)$(Configuration)\ + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + $(Configuration)\ + + + + Disabled + %(AdditionalIncludeDirectories) + true + EnableFastChecks + MultiThreadedDebugDLL + Level3 + EditAndContinue + + + + + Disabled + %(AdditionalIncludeDirectories) + EnableFastChecks + MultiThreadedDebugDLL + Level3 + ProgramDatabase + + + + + MaxSpeed + true + MultiThreadedDLL + true + Level3 + ProgramDatabase + + + true + true + true + MachineX86 + + + + + MaxSpeed + true + MultiThreadedDLL + true + Level3 + ProgramDatabase + + + true + true + true + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Kod/display/ClientServerApp/Common/Conduit.cpp b/Kod/display/ClientServerApp/Common/Conduit.cpp new file mode 100644 index 0000000..1d827f4 --- /dev/null +++ b/Kod/display/ClientServerApp/Common/Conduit.cpp @@ -0,0 +1,529 @@ +/* + * Conduit.cpp + * + * Definition of the Conduit class + * + * Author: Erik Hellström, hellstrom@isy.liu.se, 2008-12-14 + * Modified: Emil Larsson, lime@isy.liu.se, 2012-01-13 + */ + +#include +#include "Conduit.h" +#include + +// Constructor +Conduit::Conduit() { + + ptrShm = NULL; + isServer = false; + iNumSems = 0; + + hMapObject = NULL; + for(int i=0; i MAX_NUM_SEM) + return false; + + + // WIN32 IPC: Shared memory based on file mapping. + + char strKey[KEY_LEN+2]; + SECURITY_ATTRIBUTES attr; + + // Fill struct with security attributes + attr.nLength = sizeof(SECURITY_ATTRIBUTES); + attr.lpSecurityDescriptor = NULL; + attr.bInheritHandle = FALSE; + + // Convert integer array 'key' to char array 'strKey' + for(i=0; i 0))); +} + +// Wait for an event (reserve associated semaphore) +WaitResult Conduit::WaitForEvent(int index) { + + bool ret,flag; + + if(!ValidIndex(index)) + return WAIT_FAIL; + + // Perform wait + ret = Wait(index + FIRST_EVENT_SEM); + + if(!ret || !GetShutdownFlag(flag)) + return WAIT_FAIL; + if(flag) + return WAIT_CLOSE; + + return WAIT_OK; +} + +// Wait for an event with timeout +WaitResult Conduit::WaitForEvent(int index, int timeout) { + + bool ret,flag; + + if(!ValidIndex(index)) + return WAIT_FAIL; + + // Perform wait + ret = Wait(index + FIRST_EVENT_SEM,timeout); + + if(!ret || !GetShutdownFlag(flag)) + return WAIT_FAIL; + if(flag) + return WAIT_CLOSE; + + return WAIT_OK; +} + +// Cause an event (release associated sempahore) +bool Conduit::CauseEvent(int index) { + + if(!ValidIndex(index)) + return false; + else + return Signal(index + FIRST_EVENT_SEM); +} + +// Cause shutdown event +bool Conduit::CauseShutdown() { + + int i; + + // Indicate shutdown + if(!SetShutdownFlag(true)) + return false; + + // Release all semaphores but the mutex + for(i=1; iFlag; + else + ret = false; + + // Release lock + if(!ReleaseLock()) + return false; + + return ret; +} + +// Set state flag +bool Conduit::SetFlag(FlagType flag) { + + bool ret = true; + CommonData *ptr; + + // Request lock + if(!RequestLock()) + return false; + + if((ptr = GetCommonData()) != NULL) + ptr->Flag = flag; + else + ret = false; + + // Release lock + if(!ReleaseLock()) + return false; + + // Indicate change + if(!IndicateChangedFlag()) + return false; + + return ret; +} + +// Get shutdown boolean +bool Conduit::GetShutdownFlag(bool& flag) { + + bool ret = true; + CommonData *ptr; + + // Request lock + if(!RequestLock()) + return false; + + if((ptr = GetCommonData()) != NULL) + flag = ptr->DoShutdown; + else + ret = false; + + // Release lock + if(!ReleaseLock()) + return false; + + return ret; +} + +// Set shutdown boolean +bool Conduit::SetShutdownFlag(bool flag) { + + bool ret = true; + CommonData *ptr; + + // Request lock + if(!RequestLock()) + return false; + + if((ptr = GetCommonData()) != NULL) + ptr->DoShutdown = flag; + else + ret = false; + + // Release lock + if(!ReleaseLock()) + return false; + + return ret; +} + +// Check validity of semaphore index +bool Conduit::ValidIndex(int index) { + + if(index < 0 || index > (iNumSems - FIRST_EVENT_SEM)) + return false; + + return true; +} + +// Calculate number of semaphores +int Conduit::NumberOfSemaphores() { + + return(FIRST_EVENT_SEM + GetNumEvents()); +} + + + diff --git a/Kod/display/ClientServerApp/Common/Conduit.h b/Kod/display/ClientServerApp/Common/Conduit.h new file mode 100644 index 0000000..012d3f6 --- /dev/null +++ b/Kod/display/ClientServerApp/Common/Conduit.h @@ -0,0 +1,145 @@ +/* + * Conduit.h + * + * Declaration of the Conduit class + * + * Author: Erik Hellström, hellstrom@isy.liu.se, 2008-12-14 + * Modified: Emil Larsson, lime@isy.liu.se, 2012-01-13 + */ + +#ifndef CONDUIT_H_ +#define CONDUIT_H_ + +#include "ipclink.h" +#include + +// Segment key length +#define KEY_LEN 4 +// Data type of segment key +typedef unsigned short int KeyType; + +// Maximum number of semaphores +#define MAX_NUM_SEM 10 + +// First semaphore for event tracking +// Semaphore 0 : mutual exclusion +// Semaphore 1 : change of data +#define FIRST_EVENT_SEM 2 + + +#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) +// union semun is defined by including +#else +// according to X/OPEN we have to define it ourselves +union semun { + int val; // value for SETVAL + struct semid_ds *buf; // buffer for IPC_STAT, IPC_SET + wchar_t *array; // array for GETALL, SETALL + // Linux specific part: + struct seminfo *__buf; // buffer for IPC_INFO +}; +#endif + + +// +// The Conduit class +// +class Conduit { + +public: + + // Construct & Destruct + Conduit(); + virtual ~Conduit(); + + // Server initialization + bool StartServer(KeyType* key); + // Client initialization + bool StartClient(KeyType* key); + // Detach and remove shared memory segment + bool Shutdown(); + + // Request lock on shared data + bool RequestLock(); + // Release lock on shared data + bool ReleaseLock(); + + // Wait for a flag + WaitResult WaitForFlag(FlagType flag); + // Wait for a flag with timeout + WaitResult WaitForFlag(FlagType flag, int timeout); + + // Wait for an event + WaitResult WaitForEvent(int index); + // Wait for an event with timeout [ms] + WaitResult WaitForEvent(int index, int timeout); + // Cause an event + bool CauseEvent(int index); + // Cause shutdown event + bool CauseShutdown(); + + // Get state flag + bool GetFlag(FlagType& flag); + // Set state flag + bool SetFlag(FlagType flag); + + // Get shutdown boolean + bool GetShutdownFlag(bool& flag); + // Set shutdown boolean + bool SetShutdownFlag(bool flag); + + // + // Pure virtual functions + // + // Get shared data size + virtual int GetDataSize() const = 0; + // Get number of events + virtual int GetNumEvents() const = 0; + // Get pointer to common shared data + virtual CommonData* GetCommonData() const = 0; + +protected: + + // Pointer to shared memory segment + void* ptrShm; + +private: + + // Wait-operation on a semaphore + bool Wait(int index); + // Wait-operation with timeout [ms] on a semaphore + bool Wait(int index, int timeout); + // Signal-operation on semaphore + bool Signal(int index); + + // Indicate change of flag + bool IndicateChangedFlag(); + // Wait for change of flag + bool WaitForChangedFlag(); + // Wait for change with timeout of flag + bool WaitForChangedFlag(int timeout); + // Get and compare flag + bool FlagEqual(FlagType flag, FlagType& current); + + // Check validity of semaphore index + bool ValidIndex(int index); + // Calculate number of semaphores + int NumberOfSemaphores(); + + // State flag + bool isServer; + // Number of semaphores + int iNumSems; + + // WIN32 IPC: Shared memory based on file mapping. + + // Shared memory segment handle + HANDLE hMapObject; + // Semaphore handle + HANDLE hSemaphore[MAX_NUM_SEM]; + +}; + + + +#endif /* CONDUIT_H_ */ diff --git a/Kod/display/ClientServerApp/Common/ReadABuffer.cpp b/Kod/display/ClientServerApp/Common/ReadABuffer.cpp new file mode 100644 index 0000000..97bd9b5 --- /dev/null +++ b/Kod/display/ClientServerApp/Common/ReadABuffer.cpp @@ -0,0 +1,36 @@ +#include "ReadABuffer.h" + +BOOL ReadABuffer(unsigned char * lpBuf, DWORD dwToWrite, HANDLE hComm) +{ + OVERLAPPED osWrite = {0}; + DWORD dwWritten; + BOOL fRes; + + // Create this writes OVERLAPPED structure hEvent. + osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (osWrite.hEvent == NULL) + // Error creating overlapped event handle. + return FALSE; + + // Issue write. + if (!ReadFile(hComm, lpBuf, dwToWrite, &dwWritten, &osWrite)) { + if (GetLastError() != ERROR_IO_PENDING) { + // WriteFile failed, but it isn't delayed. Report error and abort. + fRes = FALSE; + } + else { + // Write is pending. + if (!GetOverlappedResult(hComm, &osWrite, &dwWritten, TRUE)) + fRes = FALSE; + else + // Write operation completed successfully. + fRes = TRUE; + } + } + else + // WriteFile completed immediately. + fRes = TRUE; + + CloseHandle(osWrite.hEvent); + return fRes; +} \ No newline at end of file diff --git a/Kod/display/ClientServerApp/Common/ReadABuffer.h b/Kod/display/ClientServerApp/Common/ReadABuffer.h new file mode 100644 index 0000000..56cf400 --- /dev/null +++ b/Kod/display/ClientServerApp/Common/ReadABuffer.h @@ -0,0 +1,20 @@ +#ifndef READABUFFER_H +#define READABUFFER_H + +#include +#include "ipclink.h" + + +BOOL ReadABuffer(unsigned char * lpBuf, DWORD dwToWrite, HANDLE hComm); + + + + + + + + + + + +#endif \ No newline at end of file diff --git a/Kod/display/ClientServerApp/Common/WriteABuffer.cpp b/Kod/display/ClientServerApp/Common/WriteABuffer.cpp new file mode 100644 index 0000000..41ecf52 --- /dev/null +++ b/Kod/display/ClientServerApp/Common/WriteABuffer.cpp @@ -0,0 +1,67 @@ + + +#include "WriteABuffer.h" + + +BOOL WriteABuffer(wchar_t* lpBuf, HANDLE hComm) +{ + OVERLAPPED osWrite = {0}; + DWORD dwWritten; + BOOL fRes; + + unsigned char printBuf[COMSTR_LEN]; + unsigned char* ptrPrintBuf; + ptrPrintBuf = &printBuf[0]; + + int lenBuf = (int) lpBuf[1]; + int ii; + +// printf("\tInteger: %d\n",lenBuf); + +// printf("\tLength of lpBuf: %d\n",wcslen(lpBuf)); + + for (ii=0; ii +#include +#include "ipclink.h" + +BOOL WriteABuffer(wchar_t * lpBuf, HANDLE hComm); + +BOOL ReadABuffer(wchar_t * lpBuf, DWORD dwToWrite, HANDLE hComm); + + + + + + + + + + + +#endif \ No newline at end of file diff --git a/Kod/display/ClientServerApp/Common/ipclink.h b/Kod/display/ClientServerApp/Common/ipclink.h new file mode 100644 index 0000000..d62429e --- /dev/null +++ b/Kod/display/ClientServerApp/Common/ipclink.h @@ -0,0 +1,80 @@ +/* + * ipclink.h + * + * Interface for the shared memory communication + * + * Author: Erik Hellström, hellstrom@isy.liu.se, 2008-12-14 + * Modified: Emil Larsson, lime@isy.liu.se, 2012-01-13 + */ + +#ifndef IPCLINK_H_ +#define IPCLINK_H_ + +// Include files for sleep-functions +#include + +// +// Shared data description +// + +// Keys +#define COM_KEY {3,1,4,6} + +// Define what is returned from wait operations +typedef unsigned int WaitResult; +#define WAIT_OK 0 +#define WAIT_FAIL 1 +#define WAIT_CLOSE 2 + +// Definition of flags +typedef unsigned int FlagType; +#define NULL_FLAG 0 + +// Exit flags +#define EXIT_OK 0 +#define EXIT_FAIL 1 + +// +// COMMON DATA +// +typedef struct structCommonData { + FlagType Flag; // State flag + bool DoShutdown; // Shutdown flag +} CommonData; + +// +// Length of , len, and bcc +// see manual for "smallprotocol package". +// +#define EXTRA_LEN 3 + + +// +// COM CONDUIT +// +// Maximum string length +//#define COMSTR_LEN 512 +// EXTRA_LEN is included +#define COMSTR_LEN 131 + + + +// Shared memory structure +typedef struct { + CommonData Common; // Common data + wchar_t string[COMSTR_LEN]; // Data string +} COMdata; + +// Flags +//#define COM_FLAG 0x01 // Example flag +// Events +#define COM_NEVENTS 2 // Number of events +#define COM_READY 0 // Ready +#define COM_REQUEST 1 // Request + +// Define sleep function +#define msleep(t) Sleep(t) + + + +#endif /* IPCLINK_H_ */ diff --git a/Kod/display/ClientServerApp/Release/Client.exe b/Kod/display/ClientServerApp/Release/Client.exe new file mode 100644 index 0000000..217d968 Binary files /dev/null and b/Kod/display/ClientServerApp/Release/Client.exe differ diff --git a/Kod/display/ClientServerApp/Release/Server.exe b/Kod/display/ClientServerApp/Release/Server.exe new file mode 100644 index 0000000..4974f18 Binary files /dev/null and b/Kod/display/ClientServerApp/Release/Server.exe differ diff --git a/Kod/display/ClientServerApp/Release/matlabclient.mexw32 b/Kod/display/ClientServerApp/Release/matlabclient.mexw32 new file mode 100644 index 0000000..d309fef Binary files /dev/null and b/Kod/display/ClientServerApp/Release/matlabclient.mexw32 differ diff --git a/Kod/display/ClientServerApp/Release/matlabclient.mexw64 b/Kod/display/ClientServerApp/Release/matlabclient.mexw64 new file mode 100644 index 0000000..e25873e Binary files /dev/null and b/Kod/display/ClientServerApp/Release/matlabclient.mexw64 differ diff --git a/Kod/display/ClientServerApp/Release/startServer.bat b/Kod/display/ClientServerApp/Release/startServer.bat new file mode 100644 index 0000000..2bcc5b9 --- /dev/null +++ b/Kod/display/ClientServerApp/Release/startServer.bat @@ -0,0 +1,15 @@ +@echo off +rem +rem Script to start modules +rem + +rem +rem 2007-09-04 +rem Erik Hellström, hellstrom@isy.liu.se. +rem + +rem | +rem | Start server +rem | +start "SERVER" cmd /C Server.exe -Pcom3 + diff --git a/Kod/display/ClientServerApp/Server/Server.cpp b/Kod/display/ClientServerApp/Server/Server.cpp new file mode 100644 index 0000000..7a7dc23 --- /dev/null +++ b/Kod/display/ClientServerApp/Server/Server.cpp @@ -0,0 +1,418 @@ +//============================================================================ +// Name : Server.cpp +// Author : Erik Hellström, hellstrom@isy.liu.se, 2008-12-14 +// Modified : Emil Larsson, lime@isy.liu.se, 2012-01-13 +// +// Description : The server sends data on request from the client. Will +// loop until an error occurs or the client requests shutdown. +// +//============================================================================ + +#include +#include +#include +#include "ComConduit.h" +#include "WriteABuffer.h" +#include "ReadABuffer.h" + +// +// Show the command-line usage +// +void Usage(char* argv[]) { + + printf("\nUsage: %s \n\n",argv[0]); + printf(" -P= Selects the COM port, ex: -Pcom1.\n"); + printf("\n\n"); +} + + +// +// Module main function +// +int main(int argc, char* argv[]) { + + + // Conduit object + ComConduit Link; + // Key + KeyType key[KEY_LEN] = COM_KEY; + // Work variables + int i; + char c,*ptr; + wchar_t data[COMSTR_LEN]; + wchar_t* ptrData = &data[0]; + + // Data that will be saved to the buffer + wchar_t dataFromLCD[COMSTR_LEN]; + wchar_t* ptrDataFromLCD = &dataFromLCD[0]; + + FlagType ret; + unsigned char portnum; + char port[] = "COM1"; + // LPCWSTR port[] = "COM1"; + int counter=1; + + + DCB dcb; + COMMTIMEOUTS CommTimeouts; + HANDLE hCom; + + WaitResult wr; + + // Initialize data + portnum = '0'; + + // + // Parse the command-line. + // + for (i=1; i: %d\n",counter, DC); +// printf("Buffer nr: %d, \t: %d\n",counter, ptrData[1]); + + + + unsigned char readChar[COMSTR_LEN]; + unsigned char* ptr_readChar = &readChar[0]; + + int jj = 0; + if (DC == DC1){ + readBufLen = 1; + ReadABuffer(ptr_readChar,readBufLen,hCom); + dataFromLCD[0] = 0; + dataFromLCD[1] = readBufLen; + dataFromLCD[2] = (wchar_t) ptr_readChar[0]; + jj = 3; + } + else if (DC == DC2){ + ReadABuffer(ptr_readChar,3,hCom); + + dataFromLCD[2] = (wchar_t) ptr_readChar[0]; + dataFromLCD[3] = (wchar_t) ptr_readChar[1]; + dataFromLCD[4] = (wchar_t) ptr_readChar[2]; + readBufLen = (int) ptr_readChar[2]; + + for (jj=0; jj < readBufLen+2; jj++){ + ReadABuffer(ptr_readChar,1,hCom); + dataFromLCD[5+jj] = (wchar_t) ptr_readChar[0]; + } + jj = jj+5; + dataFromLCD[0] = 0; + dataFromLCD[1] = readBufLen+4; + } + else{ + printf("Data in Shared memory will not be written to the LCD buffer \nbecause the data package is not correct!!! \n\n"); + printSHM = 0; + }; + + /* Stop with a "null" char */ + dataFromLCD[jj] = (wchar_t) '\0'; + +// unsigned char readChar; +// unsigned char* ptr_readChar = &readChar; +// ReadABuffer(ptr_readChar,20,hCom); + + + if (printSHM == 1){ +// printf("After %d iteration(s), Content in Shared memory (after LCD \nbuffer is written to the Shared memory): \n",counter); + printf("After %d iteration(s), Content in Shared memory (after LCD buffer is written):\n[",counter); + for (ii=2; ii < dataFromLCD[1]+1; ii++) + { + // ReadABuffer(ptr_readChar,1,hCom); + printf("%d, ", dataFromLCD[ii]); + // printf("After %d iteration(s), Content in Shared memory: %d, ",counter, dataFromLCD[ii]); + } + printf("%d]", dataFromLCD[ii]); + printf("\n\n"); + } + +// ReadABuffer(ptr_readChar,10,hCom); + +// printf("\nSend buffer nr: %d, \t: %d\n",counter, ptr_readChar[0]); +// printf("Send buffer nr: %d, \t: %d\n",counter, ptr_readChar[1]); +// printf("Send buffer nr: %d, \t: %d\n",counter, ptr_readChar[2]); +// printf("Send buffer nr: %d, \t: %d\n",counter, ptr_readChar[3]); +// printf("Send buffer nr: %d, \t: %d\n",counter, ptr_readChar[4]); +// printf("Send buffer nr: %d, \t: %d\n",counter, ptr_readChar[5]); +// printf("Send buffer nr: %d, \t: %d\n",counter, ptr_readChar[6]); +// printf("Send buffer nr: %d, \t: %d\n",counter, ptr_readChar[7]); +// printf("Send buffer nr: %d, \t: %d\n",counter, ptr_readChar[8]); +// printf("Send buffer nr: %d, \t: %d\n",counter, ptr_readChar[9]); +// printf("Send buffer nr: %d, \t: %d\n\n",counter, ptr_readChar[10]); + + counter++; + +// int ii; +// for (ii=0; ii < 10; ii++) +// { +// +// // copy each element +// dataFromLCD[ii] = (wchar_t) ptr_readChar[ii]; +// +// } +// /* Stop with a "null" char */ +// dataFromLCD[ii] = (wchar_t) '\0'; + + + // Set data in shm + if(!Link.SetData(dataFromLCD)) { + fprintf(stderr,"SetData() failed.\n"); + return EXIT_FAIL; + } + + + // printf("\t\n"); + } + + + + + // + // Shutdown + // + + // Close COM port + if(CloseHandle(hCom) == 0) { + fprintf(stderr,"\nCan't close com-port.\n"); + ret = EXIT_FAIL; + } + + // Tell eventual clients to shutdown + if(!Link.CauseShutdown()) { + fprintf(stderr,"\nCauseShutdown() failed.\n"); + ret = EXIT_FAIL; + } + // Wait for clients to shutdown + msleep(500); + // Shutdown server + if(!Link.Shutdown()) { + fprintf(stderr,"Shutdown() failed.\n"); + ret = EXIT_FAIL; + } + // Exit + if(ret == EXIT_OK) + fprintf(stdout, "\nClean exit.\n"); + + return ret; +} \ No newline at end of file diff --git a/Kod/display/ClientServerApp/Server/Server.vcproj b/Kod/display/ClientServerApp/Server/Server.vcproj new file mode 100644 index 0000000..2444780 --- /dev/null +++ b/Kod/display/ClientServerApp/Server/Server.vcproj @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Kod/display/ClientServerApp/Server/Server.vcxproj b/Kod/display/ClientServerApp/Server/Server.vcxproj new file mode 100644 index 0000000..2d8c7c2 --- /dev/null +++ b/Kod/display/ClientServerApp/Server/Server.vcxproj @@ -0,0 +1,167 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {7B05F65E-9D5F-49CE-9339-959759F4E98C} + Server + Win32Proj + + + + Application + NotSet + false + + + Application + NotSet + false + + + Application + NotSet + + + Application + NotSet + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + $(Configuration)\ + true + true + $(SolutionDir)$(Configuration)\ + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + $(Configuration)\ + false + false + + + + Disabled + ..\Common;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + EditAndContinue + + + %(AdditionalLibraryDirectories) + true + Console + MachineX86 + + + + + Disabled + ..\Common;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + ProgramDatabase + + + %(AdditionalLibraryDirectories) + true + Console + + + + + MaxSpeed + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + "..\Common";%(AdditionalIncludeDirectories) + + + true + Console + true + true + MachineX86 + + + + + MaxSpeed + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + "..\Common";%(AdditionalIncludeDirectories) + + + true + Console + true + true + + + + + + + + {8c1e78f5-0564-498a-958d-37a997bbfe49} + false + + + + + + \ No newline at end of file diff --git a/Kod/display/ClientServerApp/matlabClient/matlabClient.cpp b/Kod/display/ClientServerApp/matlabClient/matlabClient.cpp new file mode 100644 index 0000000..8f811b9 --- /dev/null +++ b/Kod/display/ClientServerApp/matlabClient/matlabClient.cpp @@ -0,0 +1,400 @@ +//============================================================================ +// Name : matlabClient.cpp +// Author : Erik Hellström, hellstrom@isy.liu.se, 2008-12-14 +// Modified : Emil Larsson, lime@isy.liu.se, 2012-01-13 +// Modified : Emil Larsson, lime@isy.liu.se, 2012-09-04 +// Data from LCD is written to the shared memory. By request, the +// data is copied to a local Matlab variable. +// +// Description : The client requests data to be sent by the server. +// +//============================================================================ + + +#include +#include +#include "ComConduit.h" +//#ifdef _CHAR16T +//#define CHAR16_T +//#endif +#include "mex.h" + +int send_communication(bool doShutdown,wchar_t* input_string,int buflen,int flag){ + // Conduit object + ComConduit Link; + // Key + KeyType key[KEY_LEN] = COM_KEY; + // Work variables + wchar_t data[COMSTR_LEN]; + wchar_t dataFromLCD[COMSTR_LEN]; + WaitResult wr; + + int retval, ii; + + + // Initialize data + retval = 0; + data[0] = '\0'; + + // strcpy((char*) data,input_string); + // wcscpy_s(&data[0],COMSTR_LEN, input_string); + + /* Copy data from input_string to data */ + for (ii=0; ii 0){ + flag = (int)*mxGetPr(prhs[0]); + }; + + plhs[1] = mxCreateDoubleMatrix(0,0,mxREAL); + // ptr_out = mxGetPr(plhs[1]); + + //if( (nrhs < 4) && (nrhs > 0)){ + // flag = (int)*mxGetPr(prhs[0]); + //}; + + + + if(flag==3){ + /* If no error, call send_communication */ + doShutdown = true; + } + + /* Do some checks of input arguments */ + if (nrhs > 0){ + if (!mxIsDouble(prhs[0])) { + mexPrintf("\nThe first input argument is not a double.\n"); + retval = 1; + } + else if (flag==4) { + mexPrintf("\nMatlab Client\n"); + mexPrintf("=============\n"); + mexPrintf("Version: %4.2f.\n", ver); + mexPrintf("Date: %s.\n", date); + retval = 4; + } + else if (!(mxGetN(prhs[0]) == 1) || !(mxGetM(prhs[0]) == 1)) { + mexPrintf("\nThe first input argument is not a scalar.\n"); + retval = 1; + } + else if (!(flag == 1 || flag == 2 || flag == 3)) { + mexPrintf("\nWrong numerical value of the first argument.\n"); + retval = 1; + } + else if (flag == 1 && nrhs < 2) { + mexPrintf("\nTo few input arguments.\n"); + retval = 1; + } + } + else{ + mexPrintf("\nTo few input arguments\n"); + retval = 1; + } + + if (nrhs > 1){ + if (!(flag == 1) || !mxIsDouble(prhs[1])) { + mexPrintf("\nFirst and second argument mismatch.\n"); + flag = 1; + retval = 1; + } + // if (!mxIsDouble(prhs[1])) { + // retval = 1; + // mexPrintf("The second argument is not a double vector.\n"); + // } + } + + if (nrhs > 2){ + mexPrintf("\nTo many input arguments\n"); + retval = 1; + } + + + /* Save output argument */ + if ((retval == 1) || (retval == 4)){ + plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL); + *(mxGetPr(plhs[0])) = retval; + } + + + + if ((nrhs > 0) && (retval == 0)){ + /* Get the length of the input string. */ + // buflen = (mxGetM(prhs[0]) * mxGetN(prhs[0])) + 1; + + // mexPrintf("\nbuflen: %d \n", buflen); + + + /* Allocate memory for input and output strings. */ + // input_buf=(char *) mxCalloc(buflen, sizeof(char)); + // external_buf=(wchar_t *) mxCalloc(buflen+1, sizeof(wchar_t)); + + /* Copy the string data from prhs[0] into a C string + * input_buf. */ + // status = mxGetString(prhs[0], input_buf, buflen); + + // if (status != 0) + // mexWarnMsgTxt("Not enough space. String will be truncated."); + + + // unsigned char *start_of_pr; + // size_t bytes_to_copy; + + + /* get the length of the input vector and pointer to data*/ + if (nrhs > 1) { + nx = mxGetN(prhs[1]); + mx = mxGetM(prhs[1]); + prtData = mxGetPr(prhs[1]); + } + else { + nx = 1; + mx = 1; + prtData = mxGetPr(prhs[0]); + } + + + /* check if the argument is a row or col vector */ + if (nx > mx) + n = nx; + else + n = mx; + + + /* Check length of buffer */ + if ((n > COMSTR_LEN) && (retval == 0) && (nrhs > 1)){ + mexPrintf("\nToo long data package.\n"); + retval = 1; + } + else if ((n < 4) && (retval == 0) && (nrhs > 1)) { + mexPrintf("\nToo short data package.\n"); + retval = 1; + } + + /* Check length of data package */ + if ((int) prtData[1] != n-3 && (nrhs > 1)) { + mexPrintf("\nIncorrect data package.\n"); + retval = 1; + } + /* Check if the package starts with DC1 or DC2 */ + else if (((int) prtData[0] != 17) && ((int) prtData[0] != 18) && (nrhs > 1)) { + mexPrintf("\nIncorrect data package.\n"); +// mexPrintf("\nIncorrect data package. %d\n", (int) prtData[0]); + retval = 1; + } + + /* Copy the double input vector to a wchar_t-string */ + unsigned short int x_short[COMSTR_LEN]; + ii = 0; + for (ii=0; ii < n; ii++) + { + x_short[ii] = (unsigned short int) prtData[ii]; + + /* Calculate checksum bcc */ + if (ii < n-1) + bcc = bcc + x_short[ii]; + + /* Check if the element is too large */ + if((x_short[ii] > 255) && (retval == 0)) { + mexPrintf("Vector element %d is larger then 255.\n", ii+1); + retval = 1; + break; + } + + /* Copy each element */ + x_short_w[ii] = (wchar_t) x_short[ii]; + // mexPrintf("\nx_short[%d]: %d \n", ii, x_short[ii]); + + } + /* Stop with a "null" char */ + x_short_w[ii] = (wchar_t) '\0'; + + /* Compare the checksum bcc with the last element */ + if ((x_short[n-1] != bcc) && (retval == 0) && (nrhs > 1)) { + mexPrintf("\nIncorrect data package.\n"); + // mexPrintf("\nChecksum %d mismatch. \n", x_short[n-1]); + //printf("\nChecksum %d mismatch. \n", x_short[n-1]); + retval = 1; + } + + /* If no error, call send_communication */ + if (retval == 0){ + retval = send_communication(doShutdown,x_short_w,n,flag); + } + + /* Save output argument */ + plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL); + *(mxGetPr(plhs[0])) = retval; + + /* Receive data from shared memory */ + if (flag == 2){ + + /* Length of Buffer */ + int lenBuf = (int) x_short_w[1]; + + //mexPrintf("\nHere: lenBuf %d: \n", lenBuf); + + /* Save in Shared memory */ + // int saveInSHM = 1; + + if ((x_short_w[1] == 1) && (x_short_w[2])){ + saveInSHM = 1; + } + else if ((x_short_w[1] == 1) && (x_short_w[2] == 21)){ + saveInSHM = 1; + } + else { + /* calculate checksum */ + bcc = 0; + for (ii=3; ii < (mwSize) x_short_w[4]+5; ii++){ + + /* Calculate checksum bcc */ + bcc = bcc + x_short_w[ii]; + } +// mexPrintf("\nHere: Checksum bcc %d: \n", bcc); + + /* Compare the checksum bcc with the last element */ + if (x_short_w[ii] != bcc){ +// mexPrintf("\nHere: Checksum %d mismatch. \n", x_short_w[lenBuf+1]); + retval = 1; + + saveInSHM = 0; + } + else { + saveInSHM = 1; + } + } + + + + if (saveInSHM == 1){ + + /* Save output argument */ + double *ptr_out; + plhs[1] = mxCreateDoubleMatrix(1,lenBuf,mxREAL); + ptr_out = mxGetPr(plhs[1]); + + for (ii=2; ii < (mwSize) lenBuf+2; ii++){ + ptr_out[ii-2] = (double) x_short_w[ii]; + // mexPrintf("\nx_short_w[%d]: %f \n", ii, ptr_out[ii-1]); + } + } + } + + } + +} + + + + + + + diff --git a/Kod/display/ClientServerApp/matlabClient/matlabClient.vcproj b/Kod/display/ClientServerApp/matlabClient/matlabClient.vcproj new file mode 100644 index 0000000..336b1f0 --- /dev/null +++ b/Kod/display/ClientServerApp/matlabClient/matlabClient.vcproj @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Kod/display/ClientServerApp/matlabClient/matlabClient.vcxproj b/Kod/display/ClientServerApp/matlabClient/matlabClient.vcxproj new file mode 100644 index 0000000..715e944 --- /dev/null +++ b/Kod/display/ClientServerApp/matlabClient/matlabClient.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {3094F281-B0A8-4B46-B1CC-A4B8B5CC596A} + matlabClient + Win32Proj + + + + StaticLibrary + Unicode + true + + + StaticLibrary + Unicode + true + + + StaticLibrary + NotSet + + + StaticLibrary + NotSet + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + $(Configuration)\ + $(SolutionDir)$(Configuration)\ + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + $(Configuration)\ + false + false + + + + Disabled + C:\Program Files %28x86%29\MATLAB\R2011b\extern\include;C:\stuff\svn\TFYY51\Code\Display\ClientServerApp\Common;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + EditAndContinue + + + + + Disabled + C:\Program Files %28x86%29\MATLAB\R2011b\extern\include;C:\stuff\svn\TFYY51\Code\Display\ClientServerApp\Common;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + ProgramDatabase + + + + + MaxSpeed + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + C:\Program Files %28x86%29\MATLAB\R2011b\extern\include;..\Common + + + true + Console + true + true + MachineX86 + C:\Program Files %28x86%29\MATLAB\R2011b\extern\include;%(AdditionalLibraryDirectories) + libmx.lib;libmex.lib;libmat.lib;%(AdditionalDependencies) + + + + + MaxSpeed + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + C:\Program Files\MATLAB\R2011b\extern\include;..\Common + + + true + Console + true + true + C:\Program Files %28x86%29\MATLAB\R2011b\extern\include;%(AdditionalLibraryDirectories) + libmx.lib;libmex.lib;libmat.lib;%(AdditionalDependencies) + + + + + + + + {8c1e78f5-0564-498a-958d-37a997bbfe49} + false + + + + + + \ No newline at end of file diff --git a/Kod/display/ClientServerApp/matlabClient/stdafx.cpp b/Kod/display/ClientServerApp/matlabClient/stdafx.cpp new file mode 100644 index 0000000..1d98a62 --- /dev/null +++ b/Kod/display/ClientServerApp/matlabClient/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// matlabClient.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/Kod/display/ClientServerApp/matlabClient/stdafx.h b/Kod/display/ClientServerApp/matlabClient/stdafx.h new file mode 100644 index 0000000..47a0d02 --- /dev/null +++ b/Kod/display/ClientServerApp/matlabClient/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/Kod/display/ClientServerApp/matlabClient/targetver.h b/Kod/display/ClientServerApp/matlabClient/targetver.h new file mode 100644 index 0000000..a38195a --- /dev/null +++ b/Kod/display/ClientServerApp/matlabClient/targetver.h @@ -0,0 +1,13 @@ +#pragma once + +// The following macros define the minimum required platform. The minimum required platform +// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run +// your application. The macros work by enabling all features available on platform versions up to and +// including the version specified. + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. +#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif + diff --git a/Kod/display/ClientServerApp/matlabMake.bat b/Kod/display/ClientServerApp/matlabMake.bat new file mode 100644 index 0000000..3ee0c82 --- /dev/null +++ b/Kod/display/ClientServerApp/matlabMake.bat @@ -0,0 +1,16 @@ +rem +rem Run to make the mex-file +rem + +rem +rem Run first mex -setup for x86 architecture, i.e., in +rem directory: "C:\Program Files (x86)\MATLAB\R2011b\bin" +rem + +rem C:\PROGRA~2\MATLAB\R2011b\bin\mex matlabClient\Debug\matlabclient.obj Common\Release\Conduit.obj Common\Release\ComConduit.obj Common\Release\WriteABuffer.obj -outdir Release\ + +C:\PROGRA~1\MATLAB\R2011b\bin\mex matlabClient\Release\matlabclient.obj Common\Release\Conduit.obj Common\Release\ComConduit.obj Common\Release\WriteABuffer.obj -outdir Release\ + + +rem +rem move matlabClient\matlabclient.mexw32 Release \ No newline at end of file diff --git a/Kod/display/DisplaySpec/edip320-8e.pdf b/Kod/display/DisplaySpec/edip320-8e.pdf new file mode 100644 index 0000000..5250332 Binary files /dev/null and b/Kod/display/DisplaySpec/edip320-8e.pdf differ diff --git a/Kod/display/display_exempel.m b/Kod/display/display_exempel.m new file mode 100644 index 0000000..c920087 --- /dev/null +++ b/Kod/display/display_exempel.m @@ -0,0 +1,161 @@ +%% Version 0.1 +% Detta skript är exempel på hur kommunikation med den tryckkänsliga +% skärmen fungerar. + +%% Start Server +addpath ClientServerApp\Release + +cd ClientServerApp\Release + +!startServer +cd ../.. +%% Diagonal linje +DC1 = 17; +ESC = 27; +Code = 'GD'; + +% x1, y1, x2, y2, (320 x 240 pixlar) +% minst signifikanta bitar till vänster +% mest signifikanta bitar till höger +arg = [0, 0, 0, 0, 63, 1, 239, 0]; + +% Save the 'small package' as a string +data = [ESC, double(Code), arg]; +len = length(data); +initStr = [DC1, len, data]; +bcc = mod(sum(initStr), 256); +str = [initStr, bcc]; + +% Skriv +matlabclient(1, str') + +%% Rita en rektangel som är fylld med mönster +DC1 = 17; +ESC = 27; +Code = 'RM'; + +% x1, y1, x2, y2, (320 x 240 pixlar) +% minst signifikanta bitar till vänster +% mest signifikanta bitar till höger +arg1 = [57, 0, 100, 0, 1, 1, 180, 0]; + +% Pattern +arg2 = 8; + +% Save the 'small package' as a string +data = [ESC, double(Code), arg1, arg2]; +len = length(data); +initStr = [DC1, len, data]; +bcc = mod(sum(initStr), 256); +str = [initStr, bcc]; + +% Skriv +matlabclient(1, str') + +%% Skriv en Test-sträng +DC1 = 17; +ESC = 27; +Code = double('ZL'); + +% x1, y1, (320 x 240 pixlar) +% minst signifikanta bitar till vänster +% mest signifikanta bitar till höger +arg1 = [117, 0, 32, 0]; + +% Textsträng +%arg2 = 'Test'; + +arg2 = 'DISPLAY!!!!!'; + +% Null +arg3 = 0; + + +% Save the 'small package' as a string +data = [ESC, double(Code), arg1, double(arg2), arg3]; +len = length(data); +initStr = [DC1, len, data]; +bcc = mod(sum(initStr), 256); +str = [initStr, bcc]; + +% Skriv +matlabclient(1, str') + +%% Definierar en Touch-area +DC1 = 17; +ESC = 27; +Code = 'AK'; + +% x1, y1, x2, y2, (320 x 240 pixlar) +% minst signifikanta bitar till vänster +% mest signifikanta bitar till höger +%arg1 = [120, 0, 100, 0, 180, 0, 130, 0]; +%arg1 = [120, 0, 100, 0, 200, 0, 120, 0]; +%arg1 = [120, 0, 130, 0, 200, 0, 160, 0]; +arg1 = [120, 0, 170, 0, 200, 0, 190, 0]; + +arg2 = 150; +arg3 = 151; + +arg4 = 'CTouch Me'; + +% Null +arg5 = 0; + +% Save the 'small package' as a string +data = [ESC, double(Code), arg1, arg2, arg3, double(arg4), arg5]; +len = length(data); +initStr = [DC1, len, data]; +bcc = mod(sum(initStr), 256); +str = [initStr, bcc]; + +% Skriv +matlabclient(1, str') +%fwrite(lcd, str) + +%% Definierar en Touch-area +DC1 = 17; +ESC = 27; +Code = 'AJ'; + +% x1, y1, x2, y2, (320 x 240 pixlar) +% minst signifikanta bitar till vänster +% mest signifikanta bitar till höger +arg1 = [100, 0, 150, 0]; + +arg2 = 2; +arg3 = [20, 20]; + +arg4 = 'RMarkera mig'; + +% Null +arg5 = 0; + +% Save the 'small package' as a string +data = [ESC, double(Code), arg1, arg2, arg3, double(arg4), arg5]; +len = length(data); +initStr = [DC1, len, data]; +bcc = mod(sum(initStr), 256); +str = [initStr, bcc]; + +matlabclient(1, str') +%fwrite(lcd, str) + +%% Radera Displayen +DC1 = 17; +ESC = 27; +Code = 'DL'; + +% Save the 'small package' as a string +data = [ESC, double(Code)]; +len = length(data); +initStr = [DC1, len, data]; +bcc = mod(sum(initStr), 256); +str = [initStr, bcc]; + +% Skriv +matlabclient(1, str') +%fwrite(lcd, str) + +%% Avsluta kommunikation med display +matlabclient(3); \ No newline at end of file -- cgit v1.2.1