├── firmware
├── hex
│ └── .gitkeep
├── hedrot-firmware
│ ├── I2Ccom.h
│ ├── hedrot_comm_protocol.h
│ ├── I2Ccom.cpp
│ ├── Mag5883.h
│ ├── ITG3200.h
│ ├── Mag5883.cpp
│ └── ADXL345.h
├── CHANGELOG.txt
└── README.txt
├── enclosure
└── Enclosure.skp
├── scripts
├── logo
│ ├── hedrot.ico
│ ├── hedrot.png
│ ├── hedrot.icns
│ └── hedrot.rsrc
├── README-DISTRIBUTION.txt
├── Mac
│ ├── build.sh
│ └── makeDistribution.sh
├── Win
│ ├── build.bat
│ └── makeDistribution.bat
└── README-BUILD.txt
├── doc
└── hedrot user manual.docx
├── command-line-demo
├── visual studio
│ ├── hedrotReceiverDemo.vcxproj.user
│ ├── hedrotReceiverDemo.sln
│ ├── hedrotReceiverDemo.vcxproj.filters
│ └── hedrotReceiverDemo.vcxproj
├── xcode
│ └── hedrotReceiverDemo.xcodeproj
│ │ ├── xcuserdata
│ │ └── baskind.xcuserdatad
│ │ │ ├── xcdebugger
│ │ │ └── Breakpoints_v2.xcbkptlist
│ │ │ └── xcschemes
│ │ │ ├── xcschememanagement.plist
│ │ │ └── headtracker_rcv_cmd.xcscheme
│ │ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ │ └── baskind.xcuserdatad
│ │ │ ├── UserInterfaceState.xcuserstate
│ │ │ └── WorkspaceSettings.xcsettings
│ │ └── project.pbxproj
└── source
│ └── hedrotReceiverDemo.c
├── hedrotReceiver
├── xcode
│ ├── hedrot_receiver.xcodeproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcuserdata
│ │ │ │ └── baskind.xcuserdatad
│ │ │ │ ├── UserInterfaceState.xcuserstate
│ │ │ │ └── WorkspaceSettings.xcsettings
│ │ ├── xcuserdata
│ │ │ └── baskind.xcuserdatad
│ │ │ │ └── xcschemes
│ │ │ │ ├── xcschememanagement.plist
│ │ │ │ └── max-external.xcscheme
│ │ └── project.pbxproj
│ ├── Info.plist
│ └── hedrot_receiver.xcconfig
├── visual studio
│ ├── hedrot_receiver.props
│ ├── max_extern_common.props
│ └── hedrot_receiver.sln
├── hedrotReceiver.maxproj
├── hedrotReceiver.json
├── patches
│ └── rs_set.maxpat
└── source
│ └── hedrot_receiver.h
├── matlab
├── quaternion_library
│ ├── quaternConj.m
│ ├── rotMat2euler.m
│ ├── quaternProd.m
│ ├── axisAngle2quatern.m
│ ├── quatern2rotMat.m
│ ├── quatern2euler.m
│ ├── euler2rotMat.m
│ ├── axisAngle2rotMat.m
│ ├── rotMat2quatern.m
│ └── TestScript.m
├── calibration
│ ├── readTextOfflineCalrawData.m
│ ├── test_script.m
│ └── ellipsoid_fit.m
├── showCookedData.m
├── showHeadtrackerDataSpectrum.m
├── readTextDataFromHeadtracker.m
└── computeAnglesMadgwick.m
├── libhedrot
├── libhedrot_utils.h
├── libhedrot_calibration.h
├── libhedrot_serialcomm.h
├── libhedrot_RTmagCalibration.h
└── libhedrot_utils.c
├── CHANGELOG.txt
└── README.md
/firmware/hex/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/enclosure/Enclosure.skp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abaskind/hedrot/HEAD/enclosure/Enclosure.skp
--------------------------------------------------------------------------------
/scripts/logo/hedrot.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abaskind/hedrot/HEAD/scripts/logo/hedrot.ico
--------------------------------------------------------------------------------
/scripts/logo/hedrot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abaskind/hedrot/HEAD/scripts/logo/hedrot.png
--------------------------------------------------------------------------------
/scripts/logo/hedrot.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abaskind/hedrot/HEAD/scripts/logo/hedrot.icns
--------------------------------------------------------------------------------
/scripts/logo/hedrot.rsrc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abaskind/hedrot/HEAD/scripts/logo/hedrot.rsrc
--------------------------------------------------------------------------------
/doc/hedrot user manual.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abaskind/hedrot/HEAD/doc/hedrot user manual.docx
--------------------------------------------------------------------------------
/scripts/README-DISTRIBUTION.txt:
--------------------------------------------------------------------------------
1 | hedrot - open-source head-tracker
2 |
3 |
4 | Hedrot Version: XXXX
5 | Firmware Version: YYYY
6 |
7 |
8 | Please read « hedrot user manual.pdf » for more information
--------------------------------------------------------------------------------
/command-line-demo/visual studio/hedrotReceiverDemo.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/command-line-demo/xcode/hedrotReceiverDemo.xcodeproj/xcuserdata/baskind.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/hedrotReceiver/xcode/hedrot_receiver.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/command-line-demo/xcode/hedrotReceiverDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/hedrotReceiver/xcode/hedrot_receiver.xcodeproj/project.xcworkspace/xcuserdata/baskind.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abaskind/hedrot/HEAD/hedrotReceiver/xcode/hedrot_receiver.xcodeproj/project.xcworkspace/xcuserdata/baskind.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/command-line-demo/xcode/hedrotReceiverDemo.xcodeproj/project.xcworkspace/xcuserdata/baskind.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abaskind/hedrot/HEAD/command-line-demo/xcode/hedrotReceiverDemo.xcodeproj/project.xcworkspace/xcuserdata/baskind.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/matlab/quaternion_library/quaternConj.m:
--------------------------------------------------------------------------------
1 | function qConj = quaternConj(q)
2 | %QUATERN2ROTMAT Converts a quaternion to its conjugate
3 | %
4 | % qConj = quaternConj(q)
5 | %
6 | % Converts a quaternion to its conjugate.
7 | %
8 | % For more information see:
9 | % http://www.x-io.co.uk/node/8#quaternions
10 | %
11 | % Date Author Notes
12 | % 27/09/2011 SOH Madgwick Initial release
13 |
14 | qConj = [q(:,1) -q(:,2) -q(:,3) -q(:,4)];
15 | end
16 |
--------------------------------------------------------------------------------
/hedrotReceiver/xcode/hedrot_receiver.xcodeproj/project.xcworkspace/xcuserdata/baskind.xcuserdatad/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges
6 |
7 | SnapshotAutomaticallyBeforeSignificantChanges
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/command-line-demo/xcode/hedrotReceiverDemo.xcodeproj/project.xcworkspace/xcuserdata/baskind.xcuserdatad/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges
6 |
7 | SnapshotAutomaticallyBeforeSignificantChanges
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/matlab/calibration/readTextOfflineCalrawData.m:
--------------------------------------------------------------------------------
1 | % readTextMagCalData.m
2 | %
3 | % read raw magnetometer calibration data recorded in a text file by hedrot
4 | %
5 | % Copyright 2017 Alexis Baskind
6 |
7 | function offlineCalrawData = readTextOfflineCalrawData(filename)
8 |
9 | fileID = fopen(filename,'r');
10 |
11 | [VAL, COUNT, ERRMSG] = fscanf (fileID, "%i, %i %i %i;\n");
12 |
13 | M=reshape(VAL,4,COUNT/4)';
14 |
15 | offlineCalrawData = M(:,2:4);
16 |
17 | fclose(fileID);
18 |
19 | endfunction
--------------------------------------------------------------------------------
/hedrotReceiver/visual studio/hedrot_receiver.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | C:\Users\Baskind\Desktop\Developpement\MaxSDK-6.1.4\c74support
6 |
7 |
8 |
9 |
10 |
11 | $(C74SUPPORT)
12 | true
13 |
14 |
15 |
--------------------------------------------------------------------------------
/matlab/showCookedData.m:
--------------------------------------------------------------------------------
1 | % showCookedData.m
2 | %
3 | % Copyright 2016 Alexis Baskind
4 |
5 | function showCookedData(headtrackerData)
6 | figure;
7 |
8 | subplot(4,1,1);
9 | plot(headtrackerData.data.gyroCalData);
10 | title("Gyroscope calibrated data");
11 |
12 | subplot(4,1,2);
13 | plot(headtrackerData.data.magCalData);
14 | title("Magnetometer calibrated data");
15 |
16 | subplot(4,1,3);
17 | plot(headtrackerData.data.accCalData);
18 | title("Accelerometer calibrated data");
19 |
20 | subplot(4,1,4);
21 | plot(headtrackerData.data.yawPitchRoll);
22 | title("Estimated Angles");legend("yaw","pitch","roll");
23 |
24 | endfunction
25 |
--------------------------------------------------------------------------------
/hedrotReceiver/hedrotReceiver.maxproj:
--------------------------------------------------------------------------------
1 | {
2 | "name" : "hedrotReceiver",
3 | "version" : 1,
4 | "creationdate" : -734034129,
5 | "modificationdate" : -710628712,
6 | "viewrect" : [ 2.0, 54.0, 300.0, 500.0 ],
7 | "autoorganize" : 0,
8 | "hideprojectwindow" : 0,
9 | "showdependencies" : 1,
10 | "autolocalize" : 0,
11 | "contents" : {
12 | "patchers" : {
13 | "hedrotReceiver.maxpat" : {
14 | "kind" : "patcher",
15 | "local" : 1,
16 | "toplevel" : 1
17 | }
18 |
19 | }
20 | ,
21 | "externals" : {
22 |
23 | }
24 |
25 | }
26 | ,
27 | "layout" : {
28 |
29 | }
30 | ,
31 | "searchpath" : {
32 |
33 | }
34 | ,
35 | "detailsvisible" : 0
36 | }
37 |
--------------------------------------------------------------------------------
/hedrotReceiver/xcode/hedrot_receiver.xcodeproj/xcuserdata/baskind.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | max-external.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 2FBBEAD608F335360078DB84
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/command-line-demo/xcode/hedrotReceiverDemo.xcodeproj/xcuserdata/baskind.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | headtracker_rcv_cmd.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 166D0E471DB3E54D007B85B9
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/matlab/quaternion_library/rotMat2euler.m:
--------------------------------------------------------------------------------
1 | function euler = rotMat2euler(R)
2 | %ROTMAT2EULER Converts a rotation matrix orientation to ZYX Euler angles
3 | %
4 | % euler = rotMat2euler(R)
5 | %
6 | % Converts a rotation matrix orientation to ZYX Euler angles where phi is
7 | % a rotation around X, theta around Y and psi around Z.
8 | %
9 | % For more information see:
10 | % http://www.x-io.co.uk/node/8#quaternions
11 | %
12 | % Date Author Notes
13 | % 27/09/2011 SOH Madgwick Initial release
14 |
15 | phi = atan2(R(3,2,:), R(3,3,:) );
16 | theta = -atan(R(3,1,:) ./ sqrt(1-R(3,1,:).^2) );
17 | psi = atan2(R(2,1,:), R(1,1,:) );
18 |
19 | euler = [phi(1,:)' theta(1,:)' psi(1,:)'];
20 | end
21 |
22 |
--------------------------------------------------------------------------------
/matlab/quaternion_library/quaternProd.m:
--------------------------------------------------------------------------------
1 | function ab = quaternProd(a, b)
2 | %QUATERNPROD Calculates the quaternion product
3 | %
4 | % ab = quaternProd(a, b)
5 | %
6 | % Calculates the quaternion product of quaternion a and b.
7 | %
8 | % For more information see:
9 | % http://www.x-io.co.uk/node/8#quaternions
10 | %
11 | % Date Author Notes
12 | % 27/09/2011 SOH Madgwick Initial release
13 |
14 | ab(:,1) = a(:,1).*b(:,1)-a(:,2).*b(:,2)-a(:,3).*b(:,3)-a(:,4).*b(:,4);
15 | ab(:,2) = a(:,1).*b(:,2)+a(:,2).*b(:,1)+a(:,3).*b(:,4)-a(:,4).*b(:,3);
16 | ab(:,3) = a(:,1).*b(:,3)-a(:,2).*b(:,4)+a(:,3).*b(:,1)+a(:,4).*b(:,2);
17 | ab(:,4) = a(:,1).*b(:,4)+a(:,2).*b(:,3)-a(:,3).*b(:,2)+a(:,4).*b(:,1);
18 | end
19 |
20 |
--------------------------------------------------------------------------------
/matlab/quaternion_library/axisAngle2quatern.m:
--------------------------------------------------------------------------------
1 | function q = axisAngle2quatern(axis, angle)
2 | %AXISANGLE2QUATERN Converts an axis-angle orientation to a quaternion
3 | %
4 | % q = axisAngle2quatern(axis, angle)
5 | %
6 | % Converts and axis-angle orientation to a quaternion where a 3D rotation
7 | % is described by an angular rotation around axis defined by a vector.
8 | %
9 | % For more information see:
10 | % http://www.x-io.co.uk/node/8#quaternions
11 | %
12 | % Date Author Notes
13 | % 27/09/2011 SOH Madgwick Initial release
14 |
15 | q0 = cos(angle./2);
16 | q1 = -axis(:,1)*sin(angle./2);
17 | q2 = -axis(:,2)*sin(angle./2);
18 | q3 = -axis(:,3)*sin(angle./2);
19 | q = [q0 q1 q2 q3];
20 | end
21 |
22 |
--------------------------------------------------------------------------------
/firmware/hedrot-firmware/I2Ccom.h:
--------------------------------------------------------------------------------
1 | // I2Ccom: I2C communication with the I2c_t3 library
2 |
3 |
4 | #ifndef _I2CCOM_H_
5 | #define _I2CCOM_H_
6 |
7 | #include "i2c_t3.h"
8 |
9 | void writeBit(uint8_t address, uint8_t subAddress, uint8_t bitnumber, uint8_t data);
10 | void writeBits(uint8_t address, uint8_t subAddress, uint8_t bitStart, uint8_t length, uint8_t data);
11 | void writeByte(uint8_t address, uint8_t subAddress, uint8_t data);
12 | bool readBit(uint8_t address, uint8_t subAddress, uint8_t bitnumber);
13 | uint8_t readBits(uint8_t address, uint8_t subAddress, uint8_t bitStart, uint8_t length);
14 | uint8_t readByte(uint8_t address, uint8_t subAddress);
15 | int8_t readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest);
16 |
17 |
18 | #endif /* _I2CCOM_H_ */
19 |
--------------------------------------------------------------------------------
/hedrotReceiver/visual studio/max_extern_common.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | <_ProjectFileVersion>11.0.60610.1
7 | ..\
8 | build\$(Configuration)_$(PlatformName)\
9 |
10 |
11 |
12 | MaxAPI.lib;MaxAudio.lib;jitlib.lib;%(AdditionalDependencies)
13 |
14 |
15 | VER_TARGETNAME="$(TargetName)";%(PreprocessorDefinitions)
16 |
17 |
18 |
--------------------------------------------------------------------------------
/matlab/quaternion_library/quatern2rotMat.m:
--------------------------------------------------------------------------------
1 | function R = quatern2rotMat(q)
2 | %QUATERN2ROTMAT Converts a quaternion orientation to a rotation matrix
3 | %
4 | % R = quatern2rotMat(q)
5 | %
6 | % Converts a quaternion orientation to a rotation matrix.
7 | %
8 | % For more information see:
9 | % http://www.x-io.co.uk/node/8#quaternions
10 | %
11 | % Date Author Notes
12 | % 27/09/2011 SOH Madgwick Initial release
13 |
14 | R(1,1,:) = 2.*q(:,1).^2-1+2.*q(:,2).^2;
15 | R(1,2,:) = 2.*(q(:,2).*q(:,3)+q(:,1).*q(:,4));
16 | R(1,3,:) = 2.*(q(:,2).*q(:,4)-q(:,1).*q(:,3));
17 | R(2,1,:) = 2.*(q(:,2).*q(:,3)-q(:,1).*q(:,4));
18 | R(2,2,:) = 2.*q(:,1).^2-1+2.*q(:,3).^2;
19 | R(2,3,:) = 2.*(q(:,3).*q(:,4)+q(:,1).*q(:,2));
20 | R(3,1,:) = 2.*(q(:,2).*q(:,4)+q(:,1).*q(:,3));
21 | R(3,2,:) = 2.*(q(:,3).*q(:,4)-q(:,1).*q(:,2));
22 | R(3,3,:) = 2.*q(:,1).^2-1+2.*q(:,4).^2;
23 | end
24 |
25 |
--------------------------------------------------------------------------------
/matlab/showHeadtrackerDataSpectrum.m:
--------------------------------------------------------------------------------
1 | % showHeadtrackerDataSpectrum.m
2 | %
3 | % Copyright 2016 Alexis Baskind
4 |
5 | function showHeadtrackerDataSpectrum (headtrackerData, stream, Nsamples, windowtype)
6 | if(nargin<3)
7 | Nsamples = headtrackerData.numberOfSamples;
8 | endif
9 |
10 | if(nargin<4)
11 | windowtype = "hanning";
12 | endif
13 |
14 | if(strcmp(windowtype,"rect"))
15 | window = ones(Nsamples,3);
16 | else
17 | eval(strcat("window = ",windowtype,"(Nsamples)*ones(1,3);"));
18 | endif
19 |
20 | %Nfft=pow2(nextpow2(headtrackerData.numberOfSamples));
21 | Nfft = 65536;
22 | %Nfft=headtrackerData.numberOfSamples;
23 | f=(0:Nfft-1)/Nfft*headtrackerData.header.samplerate;
24 | eval(strcat("X=fft(headtrackerData.data.",stream,"(1:Nsamples,:).*window,Nfft,1);"));
25 |
26 | figure;plot(f(1:Nfft/2+1),20*log10(abs(X(1:Nfft/2+1,:))));grid
27 | xlabel("frequency (Hz)");ylabel("amplitude (dB)");
28 | endfunction
29 |
--------------------------------------------------------------------------------
/matlab/quaternion_library/quatern2euler.m:
--------------------------------------------------------------------------------
1 | function euler = quatern2euler(q)
2 | %QUATERN2EULER Converts a quaternion orientation to ZYX Euler angles
3 | %
4 | % q = quatern2euler(q)
5 | %
6 | % Converts a quaternion orientation to ZYX Euler angles where phi is a
7 | % rotation around X, theta around Y and psi around Z.
8 | %
9 | % For more information see:
10 | % http://www.x-io.co.uk/node/8#quaternions
11 | %
12 | % Date Author Notes
13 | % 27/09/2011 SOH Madgwick Initial release
14 |
15 | R(1,1,:) = 2.*q(:,1).^2-1+2.*q(:,2).^2;
16 | R(2,1,:) = 2.*(q(:,2).*q(:,3)-q(:,1).*q(:,4));
17 | R(3,1,:) = 2.*(q(:,2).*q(:,4)+q(:,1).*q(:,3));
18 | R(3,2,:) = 2.*(q(:,3).*q(:,4)-q(:,1).*q(:,2));
19 | R(3,3,:) = 2.*q(:,1).^2-1+2.*q(:,4).^2;
20 |
21 | phi = atan2(R(3,2,:), R(3,3,:) );
22 | theta = -atan(R(3,1,:) ./ sqrt(1-R(3,1,:).^2) );
23 | psi = atan2(R(2,1,:), R(1,1,:) );
24 |
25 | euler = [phi(1,:)' theta(1,:)' psi(1,:)'];
26 | end
27 |
28 |
--------------------------------------------------------------------------------
/hedrotReceiver/xcode/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | ${PRODUCT_NAME}
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleLongVersionString
16 | ${PRODUCT_NAME} ${PRODUCT_VERSION}
17 | CFBundlePackageType
18 | iLaX
19 | CFBundleShortVersionString
20 | ${PRODUCT_VERSION}
21 | CFBundleSignature
22 | max2
23 | CFBundleVersion
24 | ${PRODUCT_VERSION}
25 | CSResourcesFileMapped
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/firmware/CHANGELOG.txt:
--------------------------------------------------------------------------------
1 | hedrot firmware, changelog:
2 |
3 | Version 7 (24/10/16)
4 | . changed key strings from function TransmitInfo() according to the internal variable names (easier to handle on the receiver side)
5 |
6 | Version 8 (04/08/17)
7 | . self test when the board is connected or reset:
8 | - if everything goes well, the onboard led should blink twice slowly (then it’s ready for use)
9 | - if the teensy board can connect to the daughter sensor board but cannot read its data, the onboard led blinks fast endlessly
10 | - if the teensy board cannot connect to the daughter board, nothing happens
11 | => in both latter cases, there is probably a hardware problem: either the daugther board is damaged, or there is bad contact in the connections between both boards, or the main teensy board is damaged.
12 |
13 | Version 9 (21/01/18)
14 | . First hotfix version of the firmware that works with the QMC5883 Magnetometer
15 |
16 | Version 10 (29/01/18)
17 | . clean version of the firmware that works with the QMC5883 Magnetometer
--------------------------------------------------------------------------------
/matlab/quaternion_library/euler2rotMat.m:
--------------------------------------------------------------------------------
1 | function R = euler2rotMat(phi, theta, psi)
2 | %EULER2ROTMAT Converts a ZYX Euler angle orientation to a rotation matrix
3 | %
4 | % q = euler2rotMat(axis, angle)
5 | %
6 | % Converts ZYX Euler angle orientation to a rotation matrix where phi is
7 | % a rotation around X, theta around Y and psi around Z.
8 | %
9 | % For more information see:
10 | % http://www.x-io.co.uk/node/8#quaternions
11 | %
12 | % Date Author Notes
13 | % 27/09/2011 SOH Madgwick Initial release
14 |
15 | R(1,1,:) = cos(psi).*cos(theta);
16 | R(1,2,:) = -sin(psi).*cos(phi) + cos(psi).*sin(theta).*sin(phi);
17 | R(1,3,:) = sin(psi).*sin(phi) + cos(psi).*sin(theta).*cos(phi);
18 |
19 | R(2,1,:) = sin(psi).*cos(theta);
20 | R(2,2,:) = cos(psi).*cos(phi) + sin(psi).*sin(theta).*sin(phi);
21 | R(2,3,:) = -cos(psi).*sin(phi) + sin(psi).*sin(theta).*cos(phi);
22 |
23 | R(3,1,:) = -sin(theta);
24 | R(3,2,:) = cos(theta).*sin(phi);
25 | R(3,3,:) = cos(theta).*cos(phi);
26 | end
27 |
28 |
--------------------------------------------------------------------------------
/matlab/quaternion_library/axisAngle2rotMat.m:
--------------------------------------------------------------------------------
1 | function R = axisAngle2rotMat(axis, angle)
2 | %AXISANGLE2ROTMAT Converts an axis-angle orientation to a rotation matrix
3 | %
4 | % q = axisAngle2rotMat(axis, angle)
5 | %
6 | % Converts and axis-angle orientation to a rotation matrix where a 3D
7 | % rotation is described by an angular rotation around axis defined by a
8 | % vector.
9 | %
10 | % For more information see:
11 | % http://www.x-io.co.uk/node/8#quaternions
12 | %
13 | % Date Author Notes
14 | % 27/09/2011 SOH Madgwick Initial release
15 |
16 | kx = axis(:,1);
17 | ky = axis(:,2);
18 | kz = axis(:,3);
19 | cT = cos(angle);
20 | sT = sin(angle);
21 | vT = 1 - cos(angle);
22 |
23 | R(1,1,:) = kx.*kx.*vT + cT;
24 | R(1,2,:) = kx.*ky.*vT - kz.*sT;
25 | R(1,3,:) = kx.*kz.*vT + ky.*sT;
26 |
27 | R(2,1,:) = kx.*ky.*vT + kz.*sT;
28 | R(2,2,:) = ky.*ky.*vT + cT;
29 | R(2,3,:) = ky.*kz.*vT - kx.*sT;
30 |
31 | R(3,1,:) = kx.*kz.*vT - ky.*sT;
32 | R(3,2,:) = ky.*kz.*vT + kx.*sT;
33 | R(3,3,:) = kz.*kz.*vT + cT;
34 | end
35 |
36 |
--------------------------------------------------------------------------------
/firmware/README.txt:
--------------------------------------------------------------------------------
1 | hedrot-firmware
2 |
3 | teensy firmware for the hedrot head tracker.
4 |
5 | software requirements:
6 | . Arduino IDE 1.6.11
7 | . Teensyduino 1.30 (teensy support for the Arduino IDE). During the installation of teensyduino, at least the library i2c_t3 (i2c communication library optimized for teensy, standard with Teensyduino) has to be installed
8 |
9 | hedrot-firmware can be compiled with the Arduino compiler:
10 | => open the file hedrot-firmware.ino
11 | => in the Tools Menu, select as « Board » « Teensy 3.2/3.1 »
12 | => compile
13 | the hex file of the firmware binary has then to be found manually (look at the Arduino console)
14 |
15 | alternatively, the firmware can be compiled from the command line:
16 |
17 | /Applications/Arduino.app/Contents/MacOS/Arduino -v --board teensy:avr:teensy31:usb=serial --pref build.path=$FIRMWARE_FOLDER/build --verify $FIRMWARE_FOLDER/hedrot-firmware/hedrot-firmware.ino
18 |
19 | ... where $FIRMWARE_FOLDER is an environment variable corresponding to the current folder. The main advantage of the command line method is that the hex file hedrot-firmware.ino.hex can be now easily accessed from the "build" subfolder
--------------------------------------------------------------------------------
/hedrotReceiver/visual studio/hedrot_receiver.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Express 2012 for Windows Desktop
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hedrot_receiver", "hedrot_receiver.vcxproj", "{D7D2B050-0FAC-4326-89AD-C82254541416}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Win32 = Debug|Win32
9 | Debug|x64 = Debug|x64
10 | Release|Win32 = Release|Win32
11 | Release|x64 = Release|x64
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {D7D2B050-0FAC-4326-89AD-C82254541416}.Debug|Win32.ActiveCfg = Debug|Win32
15 | {D7D2B050-0FAC-4326-89AD-C82254541416}.Debug|Win32.Build.0 = Debug|Win32
16 | {D7D2B050-0FAC-4326-89AD-C82254541416}.Debug|x64.ActiveCfg = Debug|x64
17 | {D7D2B050-0FAC-4326-89AD-C82254541416}.Debug|x64.Build.0 = Debug|x64
18 | {D7D2B050-0FAC-4326-89AD-C82254541416}.Release|Win32.ActiveCfg = Release|Win32
19 | {D7D2B050-0FAC-4326-89AD-C82254541416}.Release|Win32.Build.0 = Release|Win32
20 | {D7D2B050-0FAC-4326-89AD-C82254541416}.Release|x64.ActiveCfg = Release|x64
21 | {D7D2B050-0FAC-4326-89AD-C82254541416}.Release|x64.Build.0 = Release|x64
22 | EndGlobalSection
23 | GlobalSection(SolutionProperties) = preSolution
24 | HideSolutionNode = FALSE
25 | EndGlobalSection
26 | EndGlobal
27 |
--------------------------------------------------------------------------------
/command-line-demo/visual studio/hedrotReceiverDemo.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Express 2012 for Windows Desktop
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hedrotReceiverDemo", "hedrotReceiverDemo.vcxproj", "{F51F214F-1832-4CF4-ACC5-1A6AB701C4CC}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Win32 = Debug|Win32
9 | Debug|x64 = Debug|x64
10 | Release|Win32 = Release|Win32
11 | Release|x64 = Release|x64
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {F51F214F-1832-4CF4-ACC5-1A6AB701C4CC}.Debug|Win32.ActiveCfg = Debug|Win32
15 | {F51F214F-1832-4CF4-ACC5-1A6AB701C4CC}.Debug|Win32.Build.0 = Debug|Win32
16 | {F51F214F-1832-4CF4-ACC5-1A6AB701C4CC}.Debug|x64.ActiveCfg = Debug|x64
17 | {F51F214F-1832-4CF4-ACC5-1A6AB701C4CC}.Debug|x64.Build.0 = Debug|x64
18 | {F51F214F-1832-4CF4-ACC5-1A6AB701C4CC}.Release|Win32.ActiveCfg = Release|Win32
19 | {F51F214F-1832-4CF4-ACC5-1A6AB701C4CC}.Release|Win32.Build.0 = Release|Win32
20 | {F51F214F-1832-4CF4-ACC5-1A6AB701C4CC}.Release|x64.ActiveCfg = Release|x64
21 | {F51F214F-1832-4CF4-ACC5-1A6AB701C4CC}.Release|x64.Build.0 = Release|x64
22 | EndGlobalSection
23 | GlobalSection(SolutionProperties) = preSolution
24 | HideSolutionNode = FALSE
25 | EndGlobalSection
26 | EndGlobal
27 |
--------------------------------------------------------------------------------
/matlab/quaternion_library/rotMat2quatern.m:
--------------------------------------------------------------------------------
1 | function q = rotMat2quatern(R)
2 | %ROTMAT2QUATERN Converts a rotation matrix orientation to a quaternion
3 | %
4 | % q = axisAngle2quatern(axis, angle)
5 | %
6 | % Converts a rotation matrix orientation to a quaternion.
7 | %
8 | % For more information see:
9 | % http://www.x-io.co.uk/node/8#quaternions
10 | %
11 | % Date Author Notes
12 | % 27/09/2011 SOH Madgwick Initial release
13 |
14 | [row col numR] = size(R);
15 | q = zeros(numR, 4);
16 | K = zeros(4,4);
17 | for i = 1:numR
18 | K(1,1) = (1/3) * (R(1,1,i) - R(2,2,i) - R(3,3,i));
19 | K(1,2) = (1/3) * (R(2,1,i) + R(1,2,i));
20 | K(1,3) = (1/3) * (R(3,1,i) + R(1,3,i));
21 | K(1,4) = (1/3) * (R(2,3,i) - R(3,2,i));
22 | K(2,1) = (1/3) * (R(2,1,i) + R(1,2,i));
23 | K(2,2) = (1/3) * (R(2,2,i) - R(1,1,i) - R(3,3,i));
24 | K(2,3) = (1/3) * (R(3,2,i) + R(2,3,i));
25 | K(2,4) = (1/3) * (R(3,1,i) - R(1,3,i));
26 | K(3,1) = (1/3) * (R(3,1,i) + R(1,3,i));
27 | K(3,2) = (1/3) * (R(3,2,i) + R(2,3,i));
28 | K(3,3) = (1/3) * (R(3,3,i) - R(1,1,i) - R(2,2,i));
29 | K(3,4) = (1/3) * (R(1,2,i) - R(2,1,i));
30 | K(4,1) = (1/3) * (R(2,3,i) - R(3,2,i));
31 | K(4,2) = (1/3) * (R(3,1,i) - R(1,3,i));
32 | K(4,3) = (1/3) * (R(1,2,i) - R(2,1,i));
33 | K(4,4) = (1/3) * (R(1,1,i) + R(2,2,i) + R(3,3,i));
34 | [V,D] = eig(K);
35 | %p = find(max(D));
36 | %q = V(:,p)';
37 | q(i,:) = V(:,4)';
38 | q(i,:) = [q(i,4) q(i,1) q(i,2) q(i,3)];
39 | end
40 | end
--------------------------------------------------------------------------------
/scripts/Mac/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | echo "this builds the following binaries:"
3 | echo " . the firmware (in firmware/build/hedrot-firmware.ino.hex"
4 | echo " . the command-line demo (in command-line-demo/xcode/hedrotReceiverDemo)"
5 | echo " . the max external hedrotReceiver.mxo"
6 | echo
7 | echo "The Standlone hedrotReceiver has to be rebuilt afterwards in Max!!!!"
8 |
9 | thisDirectory=`pwd`
10 | rootDirectory=$thisDirectory/../..
11 |
12 | ArduinoAppPath=/Applications/Arduino.app/Contents/MacOS/Arduino
13 |
14 | ######### build firmware (both versions) #############################
15 | rm -rf $rootDirectory/firmware/build/*
16 |
17 | $ArduinoAppPath --verify --board teensy:avr:teensy31:usb=serial,speed=96,opt=o1std,keys=en-us --pref build.path=$rootDirectory/firmware/build $rootDirectory/firmware/hedrot-firmware/hedrot-firmware.ino
18 | cp $rootDirectory/firmware/build/hedrot-firmware.ino.hex $rootDirectory/firmware/hex/hedrot-firmware-teensy31-32.ino.hex
19 |
20 | $ArduinoAppPath --verify --board teensy:avr:teensyLC:usb=serial,speed=48,opt=osstd,keys=en-us --pref build.path=$rootDirectory/firmware/build $rootDirectory/firmware/hedrot-firmware/hedrot-firmware.ino
21 | cp $rootDirectory/firmware/build/hedrot-firmware.ino.hex $rootDirectory/firmware/hex/hedrot-firmware-teensyLC.ino.hex
22 |
23 | ######### build the command-line demo #############################
24 | xcodebuild -configuration Release -project $rootDirectory/command-line-demo/xcode/hedrotReceiverDemo.xcodeproj
25 |
26 | ######### build the Max external #############################
27 | xcodebuild -configuration Deployment -project $rootDirectory/hedrotReceiver/xcode/hedrot_receiver.xcodeproj
28 |
--------------------------------------------------------------------------------
/matlab/readTextDataFromHeadtracker.m:
--------------------------------------------------------------------------------
1 | % readTextDataFromHeadtracker.m
2 | %
3 | % read raw and cooked data recorded in a text file by hedrot
4 | %
5 | % Copyright 2016 Alexis Baskind
6 |
7 | function headtrackerData = readTextDataFromHeadtracker(filename)
8 |
9 | fileID = fopen(filename,'r');
10 |
11 | % 1° read the header
12 | readHeaderFlag = 1;
13 | while(readHeaderFlag && ((txt = fgetl (fileID)) != -1))
14 | if(strcmp(txt,""))
15 | % did we reach the end of the header?
16 | readHeaderFlag = 0;
17 | elseif(strcmp(txt,""))
18 | % is it the beginning of the header? If yes, just ignore the line
19 | else
20 | a = strsplit (txt, {', ', ';'});
21 | key = a{1};
22 | value = a{2};
23 | %split the key between spaces
24 | numberOfItems = length(strsplit(value));
25 |
26 | %case 1: single value
27 | if(numberOfItems == 1)
28 | eval(sprintf("headtrackerData.header.%s = %s;",key,value));
29 | else
30 | %case 2: several values: save as array
31 | eval(sprintf("headtrackerData.header.%s = [%s];",key,value));
32 | endif
33 | endif
34 | endwhile
35 |
36 |
37 | %2° read the data
38 | [VAL, COUNT, ERRMSG] = fscanf (fileID, "%i, %i %i %i %i %i %i %i %i %i %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f;\n");
39 | M=reshape(VAL,29,COUNT/29)';
40 |
41 | headtrackerData.data.magRawData = M(:,2:4);
42 | headtrackerData.data.accRawData = M(:,5:7);
43 | headtrackerData.data.gyroRawData = M(:,8:10);
44 | headtrackerData.data.magCalData = M(:,11:13);
45 | headtrackerData.data.accCalData = M(:,14:16);
46 | headtrackerData.data.accCalDataLP = M(:,17:19);
47 | headtrackerData.data.gyroCalData = M(:,20:22);
48 | headtrackerData.data.quaternion = M(:,23:26);
49 | headtrackerData.data.yawPitchRoll = M(:,27:29);
50 |
51 |
52 | headtrackerData.numberOfSamples = size(M,1);
53 |
54 | fclose(fileID);
55 |
56 | endfunction
--------------------------------------------------------------------------------
/libhedrot/libhedrot_utils.h:
--------------------------------------------------------------------------------
1 | //
2 | // libhedrot_utils.h
3 | // hedrot_receiver
4 | //
5 | // Created by Alexis Baskind on 17/04/17.
6 | //
7 | //
8 |
9 | #ifndef __hedrot_receiver__libhedrot_utils__
10 | #define __hedrot_receiver__libhedrot_utils__
11 |
12 | #include
13 | #include
14 |
15 | // double floating point modulo
16 | double mod(double a, double N);
17 |
18 | // round (not defined in VS2012)
19 | #if defined(_WIN32) || defined(_WIN64)
20 | double round(double value);
21 | #endif /* #if defined(_WIN32) || defined(_WIN64) */
22 |
23 | // math utils
24 |
25 | // min and max not standard in Mac
26 | #ifndef min
27 | #define min(a,b) (((a)<(b))?(a):(b))
28 | #endif
29 |
30 | #ifndef max
31 | #define max(a,b) (((a)>(b))?(a):(b))
32 | #endif
33 |
34 | #define M_PI_float (float) 3.14159265358979323846264338327950288
35 | #define DEGREE_TO_RAD M_PI_float / 180.0f
36 | #define RAD_TO_DEGREE 180.0f / M_PI_float
37 |
38 | #ifndef sign
39 | #define sign(a) (((a)>=0.0)*2-1)
40 | #endif
41 |
42 | // prototypes
43 | #if defined(_WIN32) || defined(_WIN64)
44 | # define strtok_r strtok_s // strtok_r does not exist on windows, use strtok_s instead
45 | #endif /* #if defined(_WIN32) || defined(_WIN64) */
46 |
47 | //=====================================================================================================
48 | // utils
49 | //=====================================================================================================
50 | double mod(double a, double N);
51 | float invSqrt(float x);
52 | void quaternion2YawPitchRoll(float q1, float q2, float q3, float q4, float *yaw, float *pitch, float *roll);
53 | void quaternion2RollPitchYaw(float q1, float q2, float q3, float q4, float *yaw, float *pitch, float *roll);
54 | void quaternionComposition(float q01, float q02, float q03, float q04, float q11, float q12, float q13, float q14, float *q21, float *q22, float *q23, float *q24);
55 | int stringToFloats(char* valueBuffer, float* data, int nvalues);
56 | int stringToChars(char* valueBuffer, char* data, int nvalues);
57 |
58 | void getMean3(double *samples, long numberOfSamples, float* mean);
59 | float getMean1f(float *samples, long numberOfSamples);
60 | float getStdDev1f(float *samples, long numberOfSamples, float mean);
61 |
62 |
63 | #endif /* defined(__hedrot_receiver__libhedrot_utils__) */
64 |
--------------------------------------------------------------------------------
/scripts/Win/build.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | echo this builds the following binaries (in 64 bits only):
3 | echo . the firmware (in firmware\build\hedrot-firmware.ino.hex
4 | echo . the command-line demo (in command-line-demo/xcode/hedrotReceiverDemo)
5 | echo . the max external hedrotReceiver.mxe64
6 | echo --
7 | echo The Standlone hedrotReceiver has to be rebuilt afterwards in Max!!!!
8 | echo the 64 bit version of the Standlone hedrotReceiver has to be built in the folder hedrotReceiver\standalone-Win\x64
9 | echo --
10 |
11 | set thisDirectory=%cd%
12 | set "rootDirectory=%thisDirectory%\..\.."
13 |
14 | REM ######### PATH SETTINGS #############################
15 | set "ArduinoAppPath=C:\Program Files (x86)\Arduino\arduino_debug.exe"
16 | set "MSBuildPath=C:\Windows\Microsoft.NET\Framework\v4.0.30319"
17 | set "VCTargetsPath=C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V110"
18 |
19 |
20 | REM ######### build firmware (both versions) #############################
21 | rm -rf "%rootDirectory%\firmware\build\*"
22 |
23 | "%ArduinoAppPath%" --verify --board teensy:avr:teensy31:usb=serial,speed=96,opt=o1std,keys=en-us --pref "build.path=%rootDirectory%\firmware\build" "%rootDirectory%\firmware\hedrot-firmware\hedrot-firmware.ino"
24 | copy "%rootDirectory%\firmware\build\hedrot-firmware.ino.hex" "%rootDirectory%\firmware\hex\hedrot-firmware-teensy31-32.ino.hex"
25 |
26 | "%ArduinoAppPath%" --verify --board teensy:avr:teensyLC:usb=serial,speed=48,opt=osstd,keys=en-us --pref "build.path=%rootDirectory%\firmware\build" "%rootDirectory%\firmware\hedrot-firmware\hedrot-firmware.ino"
27 | copy "%rootDirectory%\firmware\build\hedrot-firmware.ino.hex" "%rootDirectory%\firmware\hex\hedrot-firmware-teensyLC.ino.hex"
28 |
29 |
30 | REM ######### build the command-line demo #############################
31 | "%MSBuildPath%\MSBuild.exe" /t:Build "%rootDirectory%\command-line-demo\visual studio\hedrotReceiverDemo.vcxproj" /p:CommonProgramFiles="C:\Program Files (x86)\Common Files" /p:PlatformToolset=v110 /p:Configuration=Release /p:Platform=x64 /p:"VCTargetsPath=%VCTargetsPath%"
32 |
33 | REM ######### build the Max external #############################
34 | "%MSBuildPath%\MSBuild.exe" /t:Build "%rootDirectory%\hedrotReceiver\visual studio\hedrot_receiver.vcxproj" /p:CommonProgramFiles="C:\Program Files (x86)\Common Files" /p:PlatformToolset=v110 /p:Configuration=Release /p:Platform=x64 /p:"VCTargetsPath=%VCTargetsPath%"
35 |
--------------------------------------------------------------------------------
/command-line-demo/visual studio/hedrotReceiverDemo.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 | Source Files
23 |
24 |
25 | Source Files
26 |
27 |
28 | Source Files
29 |
30 |
31 | Source Files
32 |
33 |
34 | Source Files
35 |
36 |
37 |
38 |
39 | Header Files
40 |
41 |
42 | Header Files
43 |
44 |
45 | Header Files
46 |
47 |
48 | Header Files
49 |
50 |
51 | Header Files
52 |
53 |
54 | Header Files
55 |
56 |
57 |
--------------------------------------------------------------------------------
/matlab/calibration/test_script.m:
--------------------------------------------------------------------------------
1 | maxError = .05; # maximum radius deviation
2 |
3 |
4 | rawMagCalData = readTextOfflineCalrawData("/Users/baskind/Desktop/headtrackerRawMagCalibrationData.txt");
5 |
6 | # estimation 1 (free ellipsoid)
7 | [ center1, radii1, evecs1, v1 ] = ellipsoid_fit( rawMagCalData, 0 )
8 |
9 | # calculate and show calibrated data
10 | MagCalData1 = (rawMagCalData - ones(size(rawMagCalData,1),1)*center1')./(ones(size(rawMagCalData,1),1)*radii1')*evecs1;
11 | figure;plot3(MagCalData1(:,1),MagCalData1(:,2),MagCalData1(:,3),'o');
12 | xlim([-1.5 1.5]);ylim([-1.5 1.5]);zlim([-1.5 1.5]);
13 | title("points after calibration, WITH rotation");
14 |
15 | # calculate and show radius error
16 | radius_error1 = sqrt(MagCalData1(:,1).^2+MagCalData1(:,2).^2+MagCalData1(:,3).^2);
17 | figure;plot(radius_error1);
18 | title("error after calibration, WITH rotation");ylim([.8 1.2]);grid
19 | filteredIndexes = find(abs(radius_error1-1)<=maxError);
20 | min(radius_error1(filteredIndexes)), max(radius_error1(filteredIndexes))
21 |
22 |
23 | # estimation 2 (non rotated ellipsoid)
24 | [ center2, radii2, evecs2, v2 ] = ellipsoid_fit( rawMagCalData, 1 )
25 |
26 | # calculate and show calibrated data
27 | MagCalData2 = (rawMagCalData - ones(size(rawMagCalData,1),1)*center2')./(ones(size(rawMagCalData,1),1)*radii2');
28 | figure;plot3(MagCalData2(:,1),MagCalData2(:,2),MagCalData2(:,3),'o');
29 | xlim([-1.5 1.5]);ylim([-1.5 1.5]);zlim([-1.5 1.5]);
30 | title("points after calibration, NO rotation");
31 |
32 | # calculate and show radius error
33 | radius_error2 = sqrt(MagCalData2(:,1).^2+MagCalData2(:,2).^2+MagCalData2(:,3).^2);
34 | figure;plot(radius_error2);
35 | title("error after calibration, NO rotation");ylim([.8 1.2]);grid
36 | filteredIndexes = find(abs(radius_error2-1)<=maxError);
37 | min(radius_error2(filteredIndexes)), max(radius_error2(filteredIndexes))
38 |
39 | # estimation 3 (non rotated ellipsoid, second pass after removing the farther points)
40 | rawMagCalDataFiltered = rawMagCalData(filteredIndexes,:);
41 | [ center3, radii3, evecs3, v3 ] = ellipsoid_fit( rawMagCalDataFiltered, 1 )
42 |
43 | # calculate and show calibrated data
44 | MagCalData3 = (rawMagCalDataFiltered - ones(size(rawMagCalDataFiltered,1),1)*center3')./(ones(size(rawMagCalDataFiltered,1),1)*radii3');
45 | figure;plot3(MagCalData3(:,1),MagCalData3(:,2),MagCalData3(:,3),'o');
46 | xlim([-1.5 1.5]);ylim([-1.5 1.5]);zlim([-1.5 1.5]);
47 | title("points after calibration, NO rotation, second pass");
48 |
49 | # calculate and show radius error
50 | radius_error3 = sqrt(MagCalData3(:,1).^2+MagCalData3(:,2).^2+MagCalData3(:,3).^2);
51 | figure;plot(radius_error3);
52 | title("error after calibration, NO rotation, second pass");ylim([.8 1.2]);grid
53 | min(radius_error3), max(radius_error3)
54 |
--------------------------------------------------------------------------------
/matlab/quaternion_library/TestScript.m:
--------------------------------------------------------------------------------
1 | % TestScript.m
2 | %
3 | % This script tests the quaternion library functions to ensure that each
4 | % function output is consistent.
5 | %
6 | % Date Author Notes
7 | % 27/09/2011 SOH Madgwick Initial release
8 |
9 | %% Start of script
10 |
11 | close all; % close all figures
12 | clear; % clear all variables
13 | clc; % clear the command terminal
14 |
15 | %% Axis-angle to rotation matrix
16 |
17 | axis = [1 2 3];
18 | axis = axis / norm(axis);
19 | angle = pi/2;
20 |
21 | R = axisAngle2rotMat(axis, angle);
22 | num = ' % 1.5f';
23 | a = sprintf('\rAxis-angle to rotation matrix:');
24 | b = sprintf(strcat('\r', num, '\t', num, '\t', num), R(1,:));
25 | c = sprintf(strcat('\r', num, '\t', num, '\t', num), R(2,:));
26 | d = sprintf(strcat('\r', num, '\t', num, '\t', num), R(3,:));
27 | disp(strcat(a,b,c,d));
28 |
29 | %% Axis-angle to quaternion
30 |
31 | q = axisAngle2quatern(axis, angle);
32 | num = ' % 1.5f';
33 | a = sprintf('\rAxis-angle to quaternion:');
34 | b = sprintf(strcat('\r', num, '\t', num, '\t', num, '\t', num), q);
35 | disp(strcat(a,b));
36 |
37 | %% Quaternion to rotation matrix
38 |
39 | R = quatern2rotMat(q);
40 | num = ' % 1.5f';
41 | a = sprintf('\rQuaternion to rotation matrix:');
42 | b = sprintf(strcat('\r', num, '\t', num, '\t', num), R(1,:));
43 | c = sprintf(strcat('\r', num, '\t', num, '\t', num), R(2,:));
44 | d = sprintf(strcat('\r', num, '\t', num, '\t', num), R(3,:));
45 | disp(strcat(a,b,c,d));
46 |
47 | %% Rotation matrix to quaternion
48 |
49 | q = rotMat2quatern(R);
50 | num = ' % 1.5f';
51 | a = sprintf('\rRotation matrix to quaternion:');
52 | b = sprintf(strcat('\r', num, '\t', num, '\t', num, '\t', num), q);
53 | disp(strcat(a,b));
54 |
55 | %% Rotation matrix to ZYX Euler angles
56 |
57 | euler = rotMat2euler(R);
58 | num = ' % 1.5f';
59 | a = sprintf('\rRotation matrix to ZYX Euler angles:');
60 | b = sprintf(strcat('\r', num, '\t', num, '\t', num), euler);
61 | disp(strcat(a,b));
62 |
63 | %% Quaternion to ZYX Euler angles
64 |
65 | euler = quatern2euler(q);
66 | num = ' % 1.5f';
67 | a = sprintf('\rQuaternion to ZYX Euler angles:');
68 | b = sprintf(strcat('\r', num, '\t', num, '\t', num), euler);
69 | disp(strcat(a,b));
70 |
71 | %% ZYX Euler angles to rotation matrix
72 |
73 | R = euler2rotMat(euler(1), euler(2), euler(3));
74 | num = ' % 1.5f';
75 | a = sprintf('\rZYX Euler angles to rotation matrix:');
76 | b = sprintf(strcat('\r', num, '\t', num, '\t', num), R(1,:));
77 | c = sprintf(strcat('\r', num, '\t', num, '\t', num), R(2,:));
78 | d = sprintf(strcat('\r', num, '\t', num, '\t', num), R(3,:));
79 | disp(strcat(a,b,c,d));
80 |
81 | %% End of script
--------------------------------------------------------------------------------
/libhedrot/libhedrot_calibration.h:
--------------------------------------------------------------------------------
1 | //
2 | // libhedrot_calibration.h
3 | // hedrot_receiver
4 | //
5 | // Created by Alexis Baskind on 17/04/17.
6 | //
7 | // Part of code is derived from Matthieu Aussal, CMAP - Ecole Polytechnique / CNRS
8 | //
9 |
10 |
11 |
12 | #ifndef __hedrot_receiver__libhedrot_calibration__
13 | #define __hedrot_receiver__libhedrot_calibration__
14 |
15 | // constants
16 | #define MAX_NUMBER_OF_SAMPLES_FOR_CALIBRATION 100000
17 | #define MAX_CONDITION_NUMBER_OFFLINE 100000
18 | #define NORM_ERROR_TOLERANCE .05 // during calibration, all samples which norm is outside (1 +/- NORM_ERROR_TOLERANCE) after first pass of calibration are filtered out for the second pass
19 |
20 | #define MAX_ALLOWED_OFFSET 10000
21 | #define MAX_ALLOWED_SCALING 10000
22 |
23 | //=====================================================================================================
24 | // structure definition: temporary calibration data for magnetometer and accelerometer
25 | //=====================================================================================================
26 |
27 | typedef struct _calibrationData {
28 | long numberOfSamples;
29 | double rawSamples[MAX_NUMBER_OF_SAMPLES_FOR_CALIBRATION][3]; // raw samples
30 | double calSamples[MAX_NUMBER_OF_SAMPLES_FOR_CALIBRATION][3]; // calibrated samples
31 | float dataNorm[MAX_NUMBER_OF_SAMPLES_FOR_CALIBRATION]; // vector norm after calibration
32 | float conditionNumber;
33 | float normAverage; // average norm to the center
34 | float normStdDev; // standard deviation of the norm to the center
35 | float maxNormError; // maximum norm error (absolute value of norm minus averageNorm)
36 | } calibrationData;
37 |
38 |
39 | int accMagCalibration(calibrationData* calData, float* estimatedOffset, float* estimatedScaling);
40 |
41 | int myCalibration1(calibrationData* calData, float* estimatedOffset, float* estimatedScaling);
42 |
43 | int nonRotatedEllipsoidFit(calibrationData* calData, float* estimatedOffset, float* estimatedScaling, double *quadricCoefficients, double maxConditionNumber);
44 | int rotatedEllipsoidFit(calibrationData* calData, double *quadricCoefficients, double maxConditionNumber);
45 |
46 | int filterCalData(calibrationData *inCalData, calibrationData *outCalData, float center[3]);
47 |
48 | void cookCalibrationData(calibrationData* calData, float* estimatedOffset, float* estimatedScaling);
49 | void computeCalNormStatistics(calibrationData* calData, float* estimatedOffset, float* estimatedScaling, float* normAverage, float* normStdDev);
50 |
51 |
52 | #endif /* defined(__hedrot_receiver__libhedrot_calibration__) */
53 |
--------------------------------------------------------------------------------
/scripts/README-BUILD.txt:
--------------------------------------------------------------------------------
1 | how to build the binaries and create the distribution
2 |
3 |
4 | 1/ Mac OS X
5 | . edit « scripts/Mac/build.sh » and change the path to Arduino.app (variable ArduinoAppPath) if necessary
6 | . edit « Max/xcode/hedrot_receiver.xcconfig » and change the path to the « c74support » folder in the Max SDK (variable C74SUPPORT)
7 | . run « scripts/Mac/build.sh » from the command-line
8 | . open hedrotReceiver.maxproj in Max and build the standalone in the same directory
9 | . run « makeDistribution.sh » from the command-line
10 |
11 | 2/ Windows
12 | . edit « scripts/Win/build.bat » and change the following paths if necessary:
13 | - path to arduino.exe (variable ArduinoAppPath)
14 | - path to Microsoft.NET framework (variable MSBuildPath)
15 | - path to Visual Studio target V110 (variable VCTargetsPath)
16 | . edit "Max\visual studio\hedrot_receiver.props" and change the path to the « c74support » folder in the Max SDK (variable C74SUPPORT)
17 | . run « scripts/Win/build.bat »
18 | . open hedrotReceiver.maxproj in Max and build the standalone in the same directory
19 | . edit « scripts/Win/makeDistribution.bat »and change the following paths if necessary:
20 | - path to rcedit (small tool to change the app icon, available at https://github.com/electron/rcedit)
21 | . run « scripts/Win/makeDistribution.bat »
22 |
23 | In order to build hedrot binaries on Windows, a distribution of BLAS+LAPACK+LAPACKE is required. To build this distribution:
24 |
25 | . install MinGW for 64 bits. It can be found at: http://mingw-w64.org
26 |
27 | . install cmake version 2.8.12 (https://cmake.org/files/). CAUTION: lapack does not build with cmake v3+, build it with 2.8.12
28 |
29 | . download lapack sources from github (https://github.com/Reference-LAPACK). CAUTION: the latest release of the sources (3.7.0) does not build in 64 bits. The bug has been corrected afterwards (29 dec 2016). Download the repository version from 29 dec 2016, only this one will build. Here is the link:
30 | https://github.com/Reference-LAPACK/lapack-release/archive/42944f6fdee4de98fd1dd650c4f81047937635c2.zip
31 |
32 | . follow the instructions in http://icl.cs.utk.edu/lapack-for-windows/lapack/#build
33 |
34 |
35 | . in the visual studio project:
36 | 1/ add the directory containing the lapacke headers in Project Properties => Configuration Properties => C/C++ => General => Additional Include Directories
37 | 2/ add the directory containing the BLAS+lapack+lapacke .lib files in Project Properties => Configuration Properties => Linker => General => Additional Library Directories
38 |
39 |
40 | . the following DLLs built in the lapack sources are required for running the program: libblas.dll, liblapack.dll, liblapacke.dll.
41 |
42 |
43 | . copy all those dlls, as well as libgfortran-3.dll and libgcc_s_seh-1.dll, libquadmath-0.dll and libwinpthread-1.dll from the MinGW64 distribution close to the binary, i.e.:
44 | - for the command-line demo: command-line-demo\visual studio\exe\Release_x64
45 | - for the max external: in directory Max\
46 |
47 |
--------------------------------------------------------------------------------
/hedrotReceiver/xcode/hedrot_receiver.xcconfig:
--------------------------------------------------------------------------------
1 | // Xcode target configuration settings for the Max 6 SDK
2 | // Used as the basis for Xcode projects to build Max externals.
3 | //
4 | // Changes to the settings in this file will be applied to all SDK examples
5 | // To change settings for only one of the examples, override the settings using
6 | // Xcode's target inspector.
7 | //
8 | // by Timothy Place
9 | // Copyright © 2012, Cycling '74
10 |
11 |
12 | // Name & Version
13 | PRODUCT_NAME = $(PROJECT_NAME)
14 | PRODUCT_VERSION = 6.1.4
15 | ARCHS = i386 x86_64
16 |
17 |
18 | // Paths
19 | C74SUPPORT = /Volumes/Data/Developpement/SDKs/MaxSDK-6.1.4/c74support
20 | HEADER_SEARCH_PATHS = "$(C74SUPPORT)/max-includes" "$(C74SUPPORT)/msp-includes" "$(C74SUPPORT)/jit-includes"
21 | FRAMEWORK_SEARCH_PATHS = "$(C74SUPPORT)/max-includes" "$(C74SUPPORT)/msp-includes" "$(C74SUPPORT)/jit-includes"
22 | DSTROOT = $(SRCROOT)
23 | // (This next path is relative to DSTROOT)
24 | INSTALL_PATH = /..
25 |
26 |
27 | // Special Files
28 | GCC_PREFIX_HEADER = $(C74SUPPORT)/max-includes/macho-prefix.pch
29 | INFOPLIST_FILE = Info.plist
30 |
31 |
32 | // Architecture and Deployment
33 | ARCHS = i386 x86_64
34 |
35 | // The following section sets the Mac SDK version to be used.
36 | // For most projects this has little to no impact because there are no direct dependencies on OS function calls.
37 | // In those projects with OS function calls, it should be okay to use the most recent SDK version because the
38 | // MACOSX_DEPLOYMENT_TARGET will disable functionality that is unavailable in the older target OS.
39 | // For this reason, the SDKROOT variable is commented out, telling Xcode to use the default (which is the most recent SDK).
40 | //
41 | // If you do need to define the SDKROOT, different versions of Xcode have varying syntax and varying versions of the SDK present.
42 |
43 | // Xcode 3.x
44 | // SDKROOT = $(DEVELOPER_DIR)/SDKs/MacOSX10.5.sdk
45 |
46 | // Xcode 4.0 - Xcode 4.2
47 | // SDKROOT = $(DEVELOPER_DIR)/SDKs/MacOSX10.6.sdk
48 |
49 | // Xcode 4.3+
50 | // SDKROOT = macosx10.6
51 |
52 | MACOSX_DEPLOYMENT_TARGET = 10.6
53 |
54 |
55 | // Compiler Version -- leave them all commented out to get the default version provided by Xcode
56 | // GCC_VERSION = 4.2.1
57 | // GCC_VERSION = com.apple.compilers.llvmgcc42
58 | // GCC_VERSION = com.apple.compilers.llvm.clang.1_0
59 |
60 |
61 | // Preprocessor Defines
62 | GCC_PREPROCESSOR_DEFINITIONS = "DENORM_WANT_FIX = 1" "NO_TRANSLATION_SUPPORT = 1"
63 |
64 |
65 | // Static Configuration (don't change these)
66 | WRAPPER_EXTENSION = mxo;
67 | WARNING_CFLAGS = -Wmost -Wno-four-char-constants -Wno-unknown-pragmas
68 | DEPLOYMENT_LOCATION = YES
69 | GENERATE_PKGINFO_FILE = YES
70 |
71 |
72 | // Flags to enforce some build-time checks for the symbols used while not actually performing a hard link
73 | C74_SYM_LINKER_FLAGS = @$(C74SUPPORT)/max-includes/c74_linker_flags.txt
74 |
75 |
76 | // hide all symbols by default
77 | // mark a function to be exported with the C74_EXPORT macro -- most likely this will only apply to the main() function
78 | OTHER_CFLAGS = -fvisibility=hidden
79 |
--------------------------------------------------------------------------------
/libhedrot/libhedrot_serialcomm.h:
--------------------------------------------------------------------------------
1 | //
2 | // libhedrot_serialcomm.h
3 | //
4 | // Part of code is derived from "comport", (c) 1998-2005 Winfried Ritsch, Institute for Electronic Music - Graz
5 | //
6 | // Copyright 2016 Alexis Baskind
7 |
8 | #ifndef __libheadtracker_serialcomm__
9 | #define __libheadtracker_serialcomm__
10 |
11 | #include
12 |
13 | // for serial communication
14 | #if defined(_WIN32) || defined(_WIN64)
15 | #include
16 | #include
17 | #else
18 | #include
19 | #include
20 | #include /* for ioctl DTR */
21 | #include /* for TERMIO ioctl calls */
22 | #include
23 | #include
24 | #include
25 | #define INVALID_HANDLE_VALUE -1
26 | #endif /* #if defined(_WIN32) || defined(_WIN64) */
27 |
28 | // other includes
29 | #include "hedrot_comm_protocol.h"
30 |
31 | // internal constants
32 | #define MAX_NUMBER_OF_PORTS 99
33 | #define READ_BUFFER_SIZE 10000
34 |
35 | //=====================================================================================================
36 | // structure definition: headtrackerSerialcomm (all infos for serial communication with the headtracker)
37 | //=====================================================================================================
38 |
39 | typedef struct _headtrackerSerialcomm {
40 | char** availablePorts;
41 | int numberOfAvailablePorts;
42 |
43 | unsigned long numberOfReadBytes;
44 | unsigned char readBuffer[READ_BUFFER_SIZE];
45 |
46 | // information about the opened port
47 | char *serial_device_name;
48 | int portNumber; // port number in the list "availablePorts"
49 | #if defined(_WIN32) || defined(_WIN64)
50 | HANDLE comhandle; /* holds the comport handle */
51 | DCB dcb; /* holds the comm pars */
52 | DCB dcb_old; /* holds the comm pars */
53 | COMMTIMEOUTS old_timeouts;
54 | #else /* #if defined(_WIN32) || defined(_WIN64) */
55 | struct termios com_termio; /* save the com config */
56 | int comhandle; /* holds the headtracker_rcv handle */
57 | fd_set com_rfds;
58 | #endif /* #if defined(_WIN32) || defined(_WIN64) */
59 |
60 | int baud; /* holds the current baud rate */
61 |
62 | char verbose;
63 | } headtrackerSerialcomm;
64 |
65 | //=====================================================================================================
66 | // function declarations
67 | //=====================================================================================================
68 |
69 | void serial_comm_init(headtrackerSerialcomm *x);
70 | void list_comm_ports(headtrackerSerialcomm *x);
71 | void init_read_serial(headtrackerSerialcomm *x);
72 | int is_data_available(headtrackerSerialcomm *x);
73 | int write_serial(headtrackerSerialcomm *x, unsigned char *serial_byte, unsigned long numberOfBytesToWrite);
74 | #if defined(_WIN32) || defined(_WIN64)
75 | HANDLE open_serial(headtrackerSerialcomm *x, char* portName);
76 | HANDLE close_serial(headtrackerSerialcomm *x);
77 | #else /* #if defined(_WIN32) || defined(_WIN64) */
78 | int open_serial(headtrackerSerialcomm *x, char* portName);
79 | int close_serial(headtrackerSerialcomm *x);
80 | #endif
81 |
82 |
83 | #endif /* defined(__libheadtracker_serialcomm__) */
84 |
--------------------------------------------------------------------------------
/CHANGELOG.txt:
--------------------------------------------------------------------------------
1 | hedrot distribution, changelog:
2 |
3 | Version 1.3.0 (XX/XX/18)
4 | . 3D-printable enclosure ! (provided are the source Sketchup files as well as the STL files needed for printing)
5 | . now compatible with alternative version of the gy-85 board using qst QMC5883L magnetometer instead of Honeywell HMC5883L
6 | . magnetometer calibration: less constraints on so-called « absurd » estimation: now able to deal with bigger magnetic field biases that may occur with some headphones
7 | . added specific gyroscope-only estimation method (if the magnetometer does not provide reliable results)
8 | . minor: Magnetometer settings: « gain » renamed as « range »
9 |
10 | Version 1.2.2 (04/09/17)
11 | . bug solved: accelerometer hard offset could not be negative in the Max app
12 |
13 | Version 1.2.1 (04/08/17)
14 | . version 8 of the firmware. Version 8 offers exactly the same functionalities as version 7, but adds a self test when the board is connected or reset:
15 | - if everything goes well, the onboard led should blink twice slowly (then it’s ready for use)
16 | - if the teensy board can connect to the daughter sensor board but cannot read its data, the onboard led blinks fast endlessly
17 | - if the teensy board cannot connect to the daughter board, nothing happens
18 | => in both latter cases, there is probably a hardware problem: either the daugther board is damaged, or there is bad contact in the connections between both boards, or the main teensy board is damaged.
19 |
20 | Version 1.2.0 (02/08/17)
21 | . calibration routines ported in the library, completely rewritten and enhanced
22 | . experimental real-time magnetometer calibration routines
23 | . default headtracker parameters (MaxGain, acc LP filter, magnetometer rate) slightly modified for better results
24 | . added icon
25 | . added firmware for teensy LC
26 |
27 | Version 1.1.1 (07/04/17)
28 | . minor doc update
29 | . better detection if magnetometer/accelerometer is calibrated or not
30 | . bug correction on 64 bits: invSqrt sometimes provided negative results (flips the sign of the quaternion but has no effect on the estimated angles
31 |
32 | Version 1.1.0 (28/02/17)
33 | . GUI: window smaller
34 | . GUI: 3D visual display of the head tracker
35 | . ability to change the orientation of the X-Y-Z axes, the yaw-pitch-roll rotation order and to invert the rotation
36 | . doc update, examples with Reaper/Ambix, mybino and Max/Spat
37 | . OSC output: scaling options, for instance to control plugins in Reaper
38 | . the MaxBeta parameter can now be set to 0 in order to disconnect the magnetometer
39 | . Much smaller App « hedrotReceiver »
40 |
41 | Version 1.0.3 (10/02/17)
42 | . Windows version
43 | . bug solved: hedrotReceiver: only yaw transmitted by default, although « yaw/pitch/roll » is selected on startup
44 |
45 | Version 1.0.2 (20/11/16)
46 | . added sources of Max patch in the distribution
47 | . quaternion output (added an extra outlet in the Max patch)
48 |
49 | Version 1.0.1 (15/11/16)
50 | . development bugfix: possible crash with max external when compiled in Development configuration
51 | . development bugfix: problem with search paths when including hedrotReceiver.maxpat in a bigger max standalone app
52 | . added version number to attributes of hedrotReceiver.app
53 | . hedrotReceiver.app: fixed problem with receiver attributes not being updated in the GUI
54 | . hedrotReceiver.app: various GUI optimizations
55 |
56 | Version 1.0.0 (6/11/16) - initial release
--------------------------------------------------------------------------------
/hedrotReceiver/xcode/hedrot_receiver.xcodeproj/xcuserdata/baskind.xcuserdatad/xcschemes/max-external.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
48 |
49 |
50 |
56 |
57 |
58 |
59 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
74 |
80 |
81 |
82 |
83 |
85 |
86 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/command-line-demo/xcode/hedrotReceiverDemo.xcodeproj/xcuserdata/baskind.xcuserdatad/xcschemes/headtracker_rcv_cmd.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/firmware/hedrot-firmware/hedrot_comm_protocol.h:
--------------------------------------------------------------------------------
1 | // hedrot_comm_protocol.h: all constants related to communication protocol betwenn headtracker and receiver
2 | //
3 | // Copyright 2016 Alexis Baskind
4 |
5 |
6 |
7 | // "R2H_" constants correspond to messages sent from receiver to headtracker
8 | // "H2R_" constants correspond to messages sent from headtracker to receiver
9 |
10 |
11 | #ifndef _HEADTRACKER_COMM_PROTOCOL_H_
12 | #define _HEADTRACKER_COMM_PROTOCOL_H_
13 |
14 | #define HEDROT_FIRMWARE_VERSION 10
15 |
16 | //serial communication settings
17 | #define BAUDRATE 230400
18 |
19 | #define NUMBER_OF_BYTES_IN_RAWDATA_FRAME 21
20 |
21 |
22 | // reserved bytes (corresponding to ASCII codes, and cannot be used for codes):
23 | // . 44 (ASCII code corresponding to ',')
24 | // . 45 (ASCII code corresponding to '-')
25 | // . 46 (ASCII code corresponding to '.')
26 | // . from 48 to 57 (ASCII codes corresponding to digits 0-9)
27 |
28 | // standard ASCII codes for transmission of decimal values
29 | #define ASCII_0 48
30 | #define ASCII_9 57
31 | #define CARRIAGE_RETURN 13
32 | #define SPACE 32
33 | #define COMMA 44
34 | #define MINUS 45
35 | #define DOT 46
36 |
37 |
38 | // data sent from receiver to headtracker
39 | #define R2H_STOP_TRANSMISSION_CHAR 0
40 |
41 | #define R2H_SEND_INFO_CHAR 1
42 |
43 | #define R2H_START_TRANSMIT_ACCEL_OFFSET_DATA_CHAR 2
44 | #define R2H_STOP_TRANSMIT_ACCEL_OFFSET_DATA_CHAR 3
45 |
46 | #define R2H_START_TRANSMIT_ACCEL_SCALING_DATA_CHAR 4
47 | #define R2H_STOP_TRANSMIT_ACCEL_SCALING_DATA_CHAR 5
48 |
49 | #define R2H_START_TRANSMIT_MAG_OFFSET_DATA_CHAR 6
50 | #define R2H_STOP_TRANSMIT_MAG_OFFSET_DATA_CHAR 7
51 |
52 | #define R2H_START_TRANSMIT_MAG_SCALING_DATA_CHAR 8
53 | #define R2H_STOP_TRANSMIT_MAG_SCALING_DATA_CHAR 9
54 |
55 | #define R2H_TRANSMIT_SAMPLERATE 11
56 |
57 | #define R2H_TRANSMIT_GYRO_RATE 21
58 | #define R2H_TRANSMIT_GYRO_CLOCK_SOURCE 22
59 | #define R2H_TRANSMIT_GYRO_LPF_BANDWIDTH 23
60 |
61 | #define R2H_TRANSMIT_ACCEL_RANGE 31
62 | #define R2H_START_TRANSMIT_ACCEL_HARD_OFFSET 32
63 | #define R2H_STOP_TRANSMIT_ACCEL_HARD_OFFSET 33
64 | #define R2H_TRANSMIT_ACCEL_FULL_RESOLUTION_BIT 34
65 | #define R2H_TRANSMIT_ACCEL_DATARATE 35
66 |
67 | #define R2H_TRANSMIT_MAG_MEASUREMENT_BIAS 51
68 | #define R2H_TRANSMIT_MAG_SAMPLE_AVERAGING 52
69 | #define R2H_TRANSMIT_MAG_DATA_RATE 53
70 | #define R2H_TRANSMIT_MAG_GAIN 54
71 | #define R2H_TRANSMIT_MAG_MEASUREMENT_MODE 55
72 |
73 | #define R2H_AREYOUTHERE_CHAR 126
74 | #define R2H_PING_CHAR 127
75 |
76 | // data sent from headtracker to receiver
77 | // must be between 0 and 127 so that the MSB is always 0
78 | // (MSB = 1 is reserved for transmitting headtracking data)
79 | #define H2R_END_OF_RAWDATA_FRAME 0
80 | #define H2R_BOARD_OVERLOAD 1 // the teensy is too slow (the samplerate is too high)
81 |
82 |
83 | #define H2R_START_TRANSMIT_INFO_CHAR 11
84 | #define H2R_STOP_TRANSMIT_INFO_CHAR 12
85 |
86 | #define H2R_DATA_RECEIVE_ERROR_CHAR 21
87 |
88 | #define H2R_IAMTHERE_CHAR 126
89 | #define H2R_PING_CHAR 127
90 |
91 |
92 |
93 | #endif /* _HEADTRACKER_COMM_PROTOCOL_H_ */
94 |
--------------------------------------------------------------------------------
/firmware/hedrot-firmware/I2Ccom.cpp:
--------------------------------------------------------------------------------
1 | // I2Ccom: I2C communication with the I2c_t3 library
2 |
3 | #include "I2Ccom.h"
4 |
5 | // pas ultra efficace car on fait appel à deux autres fonctions
6 | void writeBit(uint8_t address, uint8_t subAddress, uint8_t bitnumber, uint8_t data) {
7 | uint8_t b = readByte(address, subAddress);
8 | b = (data != 0) ? (b | (1 << bitnumber)) : (b & ~(1 << bitnumber));
9 | writeByte(address, subAddress, b);
10 | }
11 |
12 | void writeBits(uint8_t address, uint8_t subAddress, uint8_t bitStart, uint8_t length, uint8_t data) {
13 | // 010 value to write
14 | // 76543210 bit numbers
15 | // xxx args: bitStart=4, length=3
16 | // 00011100 mask byte
17 | // 10101111 original value (sample)
18 | // 10100011 original & ~mask
19 | // 10101011 masked | value
20 | uint8_t b = readByte(address, subAddress);
21 | uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1);
22 | data <<= (bitStart - length + 1); // shift data into correct position
23 | data &= mask; // zero all non-important bits in data
24 | b &= ~(mask); // zero all important bits in existing byte
25 | b |= data; // combine data with existing byte
26 | writeByte(address, subAddress, b);
27 | }
28 |
29 | void writeByte(uint8_t address, uint8_t subAddress, uint8_t data) {
30 | Wire.beginTransmission(address); // Initialize the Tx buffer
31 | Wire.write(subAddress); // Put slave register address in Tx buffer
32 | Wire.write(data); // Put data in Tx buffer
33 | Wire.endTransmission(); // Send the Tx buffer
34 | }
35 |
36 | bool readBit(uint8_t address, uint8_t subAddress, uint8_t bitnumber) {
37 | uint8_t data; // `data` will store the register data (whole byte)
38 | Wire.beginTransmission(address); // Initialize the Tx buffer
39 | Wire.write(subAddress); // Put slave register address in Tx buffer
40 | Wire.endTransmission(I2C_NOSTOP); // Send the Tx buffer, but send a restart to keep connection alive
41 | // Wire.endTransmission(false); // Send the Tx buffer, but send a restart to keep connection alive
42 | // Wire.requestFrom(address, 1); // Read one byte from slave register address
43 | Wire.requestFrom(address, (size_t) 1); // Read one byte from slave register address
44 | data = Wire.read(); // Fill Rx buffer with result
45 | return data & (1 << bitnumber); // Return data read from slave register
46 | }
47 |
48 | uint8_t readBits(uint8_t address, uint8_t subAddress, uint8_t bitStart, uint8_t length) {
49 | // 01101001 read byte
50 | // 76543210 bit numbers
51 | // xxx args: bitStart=4, length=3
52 | // 010 masked
53 | // -> 010 shifted
54 | uint8_t b;
55 | b = readByte(address, subAddress);
56 | uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1);
57 | b &= mask;
58 | b >>= (bitStart - length + 1);
59 |
60 | return b;
61 | }
62 |
63 | uint8_t readByte(uint8_t address, uint8_t subAddress) {
64 | uint8_t data; // `data` will store the register data
65 | Wire.beginTransmission(address); // Initialize the Tx buffer
66 | Wire.write(subAddress); // Put slave register address in Tx buffer
67 | Wire.endTransmission(I2C_NOSTOP); // Send the Tx buffer, but send a restart to keep connection alive
68 | // Wire.endTransmission(false); // Send the Tx buffer, but send a restart to keep connection alive
69 | // Wire.requestFrom(address, 1); // Read one byte from slave register address
70 | Wire.requestFrom(address, (size_t) 1); // Read one byte from slave register address
71 | data = Wire.read(); // Fill Rx buffer with result
72 | return data; // Return data read from slave register
73 | }
74 |
75 | int8_t readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest) {
76 | Wire.beginTransmission(address); // Initialize the Tx buffer
77 | Wire.write(subAddress); // Put slave register address in Tx buffer
78 | Wire.endTransmission(I2C_NOSTOP); // Send the Tx buffer, but send a restart to keep connection alive
79 | // Wire.endTransmission(false); // Send the Tx buffer, but send a restart to keep connection alive
80 | uint8_t i = 0;
81 | // Wire.requestFrom(address, count); // Read bytes from slave register address
82 | Wire.requestFrom(address, (size_t) count); // Read bytes from slave register address
83 | while (Wire.available()) {
84 | dest[i++] = Wire.read(); } // Put read results in the Rx buffer
85 | return i;
86 | }
87 |
88 |
--------------------------------------------------------------------------------
/matlab/computeAnglesMadgwick.m:
--------------------------------------------------------------------------------
1 | % computeAnglesMadgwick.m
2 | %
3 | % octave/matlab version of angle estimation in libhedrot
4 | %
5 | % Part of code is derived from Sebastian Madgwick's open-source gradient descent angle estimation algorithm
6 | %
7 | % Copyright 2016 Alexis Baskind
8 |
9 | function newHeadtrackerData = computeAnglesMadgwick(headtrackerData)
10 | newHeadtrackerData = headtrackerData;
11 |
12 | SamplePeriod = 1/newHeadtrackerData.header.samplerate;
13 | alphaMin = newHeadtrackerData.header.accLPalphaMin;
14 | alphaGain = newHeadtrackerData.header.accLPalphaGain;
15 | BetaMax = newHeadtrackerData.header.MadgwickBetaMax;
16 | BetaGain = newHeadtrackerData.header.MadgwickBetaGain;
17 |
18 | accLPstate = newHeadtrackerData.data.accCalData(1, :);
19 |
20 | %the first value is left as it was calculated by the headtracker receiver (initialization)
21 | for t = 2:length(newHeadtrackerData.data.gyroCalData(:,1))
22 | [newHeadtrackerData.data.quaternion(t, :), newHeadtrackerData.data.step(t, :), accLPstate] = Update(newHeadtrackerData.data.quaternion(t-1, :), SamplePeriod, alphaMin, alphaGain, BetaMax, BetaGain, accLPstate, newHeadtrackerData.data.gyroCalData(t,:), newHeadtrackerData.data.accCalData(t,:), newHeadtrackerData.data.magCalData(t,:));
23 | end
24 |
25 | eulerAngles = quatern2euler(quaternConj(newHeadtrackerData.data.quaternion)) * (180/pi); %roll pitch yaw
26 | newHeadtrackerData.data.yawPitchRoll = [eulerAngles(:,3) eulerAngles(:,2) eulerAngles(:,1)];
27 | endfunction
28 |
29 |
30 | %% method (derived from MadgwickAHRS.m without classdef)
31 | function [outputQuaternion, step, accLPstate] = Update(inputQuaternion, SamplePeriod, alphaMin, alphaGain, BetaMax, BetaGain, oldAccLPstate, GyroscopeData, AccelerometerData, MagnetometerData)
32 | q = inputQuaternion; % short name local variable for readability
33 |
34 | % compute gyro_norm2
35 | gyro_norm2 = GyroscopeData(1)^2 + GyroscopeData(2)^2 + GyroscopeData(3)^2;
36 |
37 | % lowpass Accelerometer data
38 | accLPalpha = alphaMin + (1 - alphaMin) * min(max(alphaGain * gyro_norm2,0),1);
39 | AccelerometerDataLP(1) = accLPalpha * AccelerometerData(1) + (1 - accLPalpha) * oldAccLPstate(1);
40 | AccelerometerDataLP(2) = accLPalpha * AccelerometerData(2) + (1 - accLPalpha) * oldAccLPstate(2);
41 | AccelerometerDataLP(3) = accLPalpha * AccelerometerData(3) + (1 - accLPalpha) * oldAccLPstate(3);
42 | %filter state update
43 | accLPstate(1) = AccelerometerDataLP(1);
44 | accLPstate(2) = AccelerometerDataLP(2);
45 | accLPstate(3) = AccelerometerDataLP(3);
46 |
47 | % Normalise Accelerometer measurement
48 | if(norm(AccelerometerData) == 0), return; end % handle NaN
49 | AccelerometerDataLP = AccelerometerDataLP / norm(AccelerometerDataLP); % normalise magnitude
50 |
51 | % Normalise Magnetometer measurement
52 | if(norm(MagnetometerData) == 0), return; end % handle NaN
53 | MagnetometerData = MagnetometerData / norm(MagnetometerData); % normalise magnitude
54 |
55 | % Reference direction of Earth's magnetic feild
56 | h = quaternProd(q, quaternProd([0 MagnetometerData], quaternConj(q)));
57 | b = [0 norm([h(2) h(3)]) 0 h(4)];
58 |
59 | % Gradient decent algorithm corrective step
60 | F = [2*(q(2)*q(4) - q(1)*q(3)) - AccelerometerDataLP(1)
61 | 2*(q(1)*q(2) + q(3)*q(4)) - AccelerometerDataLP(2)
62 | 2*(0.5 - q(2)^2 - q(3)^2) - AccelerometerDataLP(3)
63 | 2*b(2)*(0.5 - q(3)^2 - q(4)^2) + 2*b(4)*(q(2)*q(4) - q(1)*q(3)) - MagnetometerData(1)
64 | 2*b(2)*(q(2)*q(3) - q(1)*q(4)) + 2*b(4)*(q(1)*q(2) + q(3)*q(4)) - MagnetometerData(2)
65 | 2*b(2)*(q(1)*q(3) + q(2)*q(4)) + 2*b(4)*(0.5 - q(2)^2 - q(3)^2) - MagnetometerData(3)];
66 | J = [-2*q(3), 2*q(4), -2*q(1), 2*q(2)
67 | 2*q(2), 2*q(1), 2*q(4), 2*q(3)
68 | 0, -4*q(2), -4*q(3), 0
69 | -2*b(4)*q(3), 2*b(4)*q(4), -4*b(2)*q(3)-2*b(4)*q(1), -4*b(2)*q(4)+2*b(4)*q(2)
70 | -2*b(2)*q(4)+2*b(4)*q(2), 2*b(2)*q(3)+2*b(4)*q(1), 2*b(2)*q(2)+2*b(4)*q(4), -2*b(2)*q(1)+2*b(4)*q(3)
71 | 2*b(2)*q(3), 2*b(2)*q(4)-4*b(4)*q(2), 2*b(2)*q(1)-4*b(4)*q(3), 2*b(2)*q(2)];
72 | step = (J'*F);
73 | step = step / norm(step); % normalise step magnitude
74 |
75 |
76 | % compute beta
77 | Beta = BetaMax * (1 - min(max(BetaGain * gyro_norm2,0),1));
78 |
79 | % Compute rate of change of quaternion
80 | qDot = 0.5 * quaternProd(q, [0 GyroscopeData(1) GyroscopeData(2) GyroscopeData(3)]) - Beta * step';
81 |
82 | % Integrate to yield quaternion
83 | q = q + qDot * SamplePeriod;
84 | outputQuaternion = q / norm(q); % normalise quaternion
85 | end
86 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # hedrot
2 |
3 | ### Note: the development of hedrot has been stopped and the project is currently not maintained.
4 |
5 | ## What is hedrot?
6 | Hedrot (for "head rotation tracker") is a low-cost (around 25 euros with a teensy LC) and efficient open-source hardware/software solution for head tracking. Hedrot is especially suitable for binaural rendering (3D-Audio on headphones), and has been initially designed for use with the binaural renderer Bipan as part of the Bili Project http://www.bili-project.org/.
7 |
8 | Hedrot provides an estimation of the rotation of the sensor (thus of the head if the sensor is attached to headphones) for the most usual x-y-z coordinate systems, either as a quaternion, or as a set of 3 orientation angles yaw, pitch and roll with two different orders (yaw-pitch-roll or roll-pitch-yaw). The main application provided with the distribution, hedrotReceiver, sends this information as OSC streams, with the extra possibility to scale each stream independently.
9 |
10 | Contrary to several generic open-source head tracking solutions, hedrot relies on and has been optimized for specific widely spread and efficient hardware parts, i.e. a Teensy 3 or Teensy LC board (optimized Arduino-like board) combined to a IMU/MARG daughter board with 3 common sensors (Analog Devices ADXL345 accelerometer, Honeywell HMC5883L magnetometer and Invensense ITG-3200 gyroscope).
11 |
12 | The estimation algorithm is based on a modified version of the precise and efficient open-source gradient descent algorithm from Sebastian Madgwick. The technology was dramatically optimized for speed: the head tracker can deliver data at rates up to 2 kHz. The hardware latency of the Teensy board and USB communication relies below 2 ms. The overall latency (including sensor latency and time constant of the algorithm) is being currently measured.
13 |
14 | ## Licensing and Credits
15 | The first development phase of Hedrot has achieved in collaboration with the Conservatoire National Supérieur de Musique et de Danse de Paris (http://www.conservatoiredeparis.fr/) as part of the "Bili" project (http://www.bili-project.org/).
16 |
17 | Matthieu Aussal (CMAP - Ecole Polytechnique / CNRS) contributed to new calibration routines (version > 1.2)
18 |
19 | Hedrot is licensed under the terms of the GNU General Public License (version 3) as published by the Free Software Foundation.
20 |
21 | Part of code is derived from Sebastian Madgwick's open-source gradient descent angle estimation algorithm (http://x-io.co.uk/open-source-imu-and-ahrs-algorithms/)
22 |
23 |
24 | ### Developers and Contributors
25 | * Alexis Baskind (sound engineer, main developer)
26 | * Jean-Christophe Messonnier (sound engineer)
27 | * Jean-Marc Lyzwa (sound engineer)
28 | * Matthieu Aussal, CMAP - Ecole Polytechnique / CNRS (calibration routines)
29 |
30 |
31 | ## Hardware Requirements
32 | - Head tracker parts:
33 | - 1 Teensy 3 board (tested with versions 3.1, 3.2 and LC)
34 | - 1 USB to Micro-USB 2.0 cable, minimum length 1.5 m
35 | - 1 gy85 IMU daughter board with the following sensors:
36 | - 1 Analog Devices ADXL345 accelerometer
37 | - 1 Honeywell HMC5883L compass (magnetometer)
38 | - 1 Invensense ITG3200 gyroscope
39 |
40 | ## Software Requirements
41 | - Mac OS 10.9.5 or later
42 | - Windows: Windows 7 or later
43 | - the teensy.app firmware flash loader
44 | - Windows: Microsoft Visual C++ 2012 Redistributable package (x86 or x64 version, depending on if a 32 or 64 bit version of the hedrot is being used)
45 | - Windows: Teensy serial driver (called "Windows Serial Installer" on https://www.pjrc.com)
46 |
47 | ## Extra Requirements for building from sources:
48 | - Xcode version 8.2 or later (for Mac), or Visual Studio 2012 (for Windows)
49 | - Windows: a windows version of awk (like gawk) and the program 7-zip to make the package
50 | - Max version 6 at least (to rebuild the "hedrotReceiver" application. Not needed otherwise)
51 | - Arduino IDE 1.8.3
52 | - Windows: a distribution of BLAS, Lapack and LAPACKE. See README-BUILD.txt for more information about how to build it
53 | - Teensyduino 1.37 (teensy support for the Arduino IDE and the teensy USB serial driver on Windows), with at least the i2c_t3 library. Note: Teensyduino already includes the Teensy serial driver on Windows
54 |
55 | ## Project organisation
56 | - the empty folder "build" is where the distribution will be built
57 | - the folder "command-line-demo" contains the sources of the command-line demonstration
58 | - the folder "doc" contains the documentation
59 | - the folder "examples" contains application examples
60 | - the folder "firmware" contains the sources of the firmware to be uploaded in the teensy board
61 | - the folder "libhedrot" contains the sources of the receiver library
62 | - the folder "matlab" contains programs for matlab and octave
63 | - the folder "Max" contains the sources of the main receiver application, written in Max
64 | - the folder "scripts" contains the scripts for building binaries and the distribution
65 |
--------------------------------------------------------------------------------
/scripts/Mac/makeDistribution.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | echo "Before running this script, be sure that: "
3 | echo " 1/ all binaries have been compiled"
4 | echo " 2/ a pdf version of the doc has been created"
5 | echo " 3/ the Max standalone hedrotReceiver has been built."
6 |
7 | today=$(date +"%y-%m-%d")
8 |
9 | thisDirectory=`pwd`
10 | rootDirectory=$thisDirectory/../..
11 | destDirectory=$rootDirectory/build/forPackaging
12 |
13 | hedrotVersion=`awk '/^#define HEDROT_VERSION / { print $3 }' $rootDirectory/libhedrot/libhedrot.h | sed 's/"//g'`
14 | hedrotVersionMessage="hedrot version: $hedrotVersion"
15 | echo $hedrotVersionMessage
16 |
17 | hedrotFirmwareVersion=`awk '/^#define HEDROT_FIRMWARE_VERSION / { print $3 }' $rootDirectory/firmware/hedrot-firmware/hedrot_comm_protocol.h`
18 | hedrotFirmwareVersionMessage="Headtracker Firmware version: $hedrotFirmwareVersion"
19 | echo $hedrotFirmwareVersionMessage
20 |
21 | packageName="hedrot-$hedrotVersion-${today}-Mac"
22 | packageFolder="$destDirectory/$packageName"
23 |
24 |
25 | ######### create destination folder #############################
26 | rm -rf $destDirectory/*
27 | mkdir $packageFolder
28 |
29 | ######### prepare and copy Max Standalone #############################
30 |
31 | #copy the standalone and the default preset file
32 | cp -R $rootDirectory/hedrotReceiver/hedrotReceiver.app $packageFolder
33 | cp -R $rootDirectory/hedrotReceiver/hedrotReceiver.json $packageFolder
34 |
35 | appcontentsdirectory=$packageFolder/hedrotReceiver.app/Contents
36 |
37 | #update the version number and icon in Info.plist
38 | /usr/libexec/PlistBuddy -c "Set :CFBundleGetInfoString '${hedrotVersion}'" $appcontentsdirectory/Info.plist
39 | /usr/libexec/PlistBuddy -c "Set :CFBundleLongVersionString '${hedrotVersion}'" $appcontentsdirectory/Info.plist
40 | /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString '${hedrotVersion}'" $appcontentsdirectory/Info.plist
41 | /usr/libexec/PlistBuddy -c "Set :CFBundleVersion '${hedrotVersion}'" $appcontentsdirectory/Info.plist
42 | /usr/libexec/PlistBuddy -c "Set :CFBundleIconFile 'hedrot.icns'" $appcontentsdirectory/Info.plist
43 |
44 |
45 | rm $appcontentsdirectory/Resources/*.icns
46 | cp ../logo/hedrot.icns $appcontentsdirectory/Resources/
47 |
48 |
49 |
50 | ######### copy the command-line-demo #############################
51 | mkdir $packageFolder/command-line-demo
52 | cp "$rootDirectory/command-line-demo/xcode/hedrotReceiverDemo" "$packageFolder/command-line-demo/"
53 |
54 | ######### copy the firmware (both versions) #############################
55 | mkdir $packageFolder/firmware
56 | cp "$rootDirectory/firmware/hex/hedrot-firmware-teensy31-32.ino.hex" "$packageFolder/firmware/hedrot-firmware-teensy31-32_version_$hedrotFirmwareVersion.hex"
57 | cp "$rootDirectory/firmware/hex/hedrot-firmware-teensyLC.ino.hex" "$packageFolder/firmware/hedrot-firmware-teensyLC_version_$hedrotFirmwareVersion.hex"
58 | cp "$rootDirectory/firmware/CHANGELOG.txt" "$packageFolder/firmware/"
59 |
60 | ######### copy the max source code and external #############################
61 | mkdir $packageFolder/Max
62 | cp $rootDirectory/hedrotReceiver/hedrotReceiver.json $packageFolder/Max/
63 | cp $rootDirectory/hedrotReceiver/patches/*.maxpat $packageFolder/Max/
64 | cp -R $rootDirectory/hedrotReceiver/hedrot_receiver.mxo $packageFolder/Max/
65 |
66 | ######### copy the examples folder #############################
67 | mkdir $packageFolder/examples
68 | cp -R $rootDirectory/examples $packageFolder/examples
69 |
70 | ######### copy the doc #############################
71 | cp "$rootDirectory/doc/hedrot user manual.pdf" "$packageFolder/"
72 |
73 | ######### copy the license file #############################
74 | cp "$rootDirectory/LICENSE" "$packageFolder/"
75 |
76 | ######### copy the CHANGELOG.txt file #############################
77 | cp "$rootDirectory/CHANGELOG.txt" "$packageFolder/"
78 |
79 | ######### copy and update the main README.txt file #############################
80 | cp "$rootDirectory/scripts/README-DISTRIBUTION.txt" "$packageFolder/README.txt"
81 | perl -pi -w -e "s/Hedrot Version: XXXX/Hedrot Version: $hedrotVersion/g;" $packageFolder/README.txt
82 | perl -pi -w -e "s/Firmware Version: YYYY/Firmware Version: $hedrotFirmwareVersion/g;" $packageFolder/README.txt
83 |
84 | ######### change icon of the app folder #############################
85 | Rez -append ../logo/hedrot.rsrc -o $packageFolder$'/Icon\r'
86 | SetFile -a C $packageFolder/
87 | SetFile -a V $packageFolder$'/Icon\r'
88 |
89 |
90 | ######### DMG #############################
91 |
92 | #erase the DMG if it exists
93 | rm "$rootDirectory/build/$packageName.dmg"
94 |
95 | #create the DMG
96 | # the following line (creating a .Trash) is a hocus-pocus work-around that some times works when hdiutils does not succeed and returns an error 5341 (bug)
97 | touch $destDirectory/.Trash
98 |
99 | hdiutil create "$rootDirectory/build/$packageName.dmg" -volname "$packageName" -fs HFS+ -srcfolder $destDirectory
100 |
101 | #erase temp build directory
102 | rm -rf $destDirectory/*
--------------------------------------------------------------------------------
/firmware/hedrot-firmware/Mag5883.h:
--------------------------------------------------------------------------------
1 | // Mag5883.h: Mag5883 I2C device methods for both Magnetometers used in gy-85 boards:
2 | // . Honeywell HMC5883L
3 | // . QMC5883L
4 | // part of code derived from [DFRobot](http://www.dfrobot.com), 2017
5 | // part of code derived from I2Cdev library
6 |
7 | #ifndef Mag5883_H
8 | #define Mag5883_H
9 |
10 | #include "I2Ccom.h"
11 |
12 |
13 | #define HMC5883L_ADDRESS 0x1E
14 | #define QMC5883_ADDRESS 0x0D
15 |
16 |
17 | #define HMC5883L_REG_CONFIG_A 0x00
18 | #define HMC5883L_REG_CONFIG_B 0x01
19 | #define HMC5883L_REG_MODE 0x02
20 | #define HMC5883L_REG_OUT_X_M 0x03
21 | #define HMC5883L_REG_OUT_X_L 0x04
22 | #define HMC5883L_REG_OUT_Z_M 0x05
23 | #define HMC5883L_REG_OUT_Z_L 0x06
24 | #define HMC5883L_REG_OUT_Y_M 0x07
25 | #define HMC5883L_REG_OUT_Y_L 0x08
26 | #define HMC5883L_REG_STATUS 0x09
27 | #define HMC5883L_REG_IDENT_A 0x0A
28 | #define HMC5883L_REG_IDENT_B 0x0B
29 | #define HMC5883L_REG_IDENT_C 0x0C
30 |
31 |
32 | #define QMC5883_REG_OUT_X_M 0x01
33 | #define QMC5883_REG_OUT_X_L 0x00
34 | #define QMC5883_REG_OUT_Z_M 0x05
35 | #define QMC5883_REG_OUT_Z_L 0x04
36 | #define QMC5883_REG_OUT_Y_M 0x03
37 | #define QMC5883_REG_OUT_Y_L 0x02
38 | #define QMC5883_REG_STATUS 0x06
39 | #define QMC5883_REG_CONFIG_1 0x09
40 | #define QMC5883_REG_CONFIG_2 0x0A
41 | #define QMC5883_REG_IDENT_B 0x0B
42 | #define QMC5883_REG_IDENT_C 0x20
43 | #define QMC5883_REG_IDENT_D 0x21
44 |
45 | // measurement bias
46 | #define HMC5883L_CRA_BIAS_BIT 1
47 | #define HMC5883L_CRA_BIAS_LENGTH 2
48 |
49 | #define HMC5883L_BIAS_NORMAL 0x00
50 | #define HMC5883L_BIAS_POSITIVE 0x01
51 | #define HMC5883L_BIAS_NEGATIVE 0x02
52 |
53 | // range
54 | #define HMC5883L_CRB_RANGE_BIT 7
55 | #define HMC5883L_CRB_RANGE_LENGTH 3
56 |
57 | #define HMC5883L_RANGE_0_88G 0x00
58 | #define HMC5883L_RANGE_1_3G 0x01
59 | #define HMC5883L_RANGE_1_9G 0x02
60 | #define HMC5883L_RANGE_2_5G 0x03
61 | #define HMC5883L_RANGE_4_G 0x04
62 | #define HMC5883L_RANGE_4_7G 0x05
63 | #define HMC5883L_RANGE_5_6G 0x06
64 | #define HMC5883L_RANGE_8_1G 0x07
65 |
66 | #define QMC5883_CRB_RANGE_BIT 5
67 | #define QMC5883_CRB_RANGE_LENGTH 2
68 |
69 | #define QMC5883_RANGE_2G 0x00,
70 | #define QMC5883_RANGE_8G 0x01
71 |
72 | // sample averaging
73 | #define HMC5883L_CRA_AVERAGE_BIT 6
74 | #define HMC5883L_CRA_AVERAGE_LENGTH 2
75 |
76 | #define HMC5883L_SAMPLES_8 0b11
77 | #define HMC5883L_SAMPLES_4 0b10
78 | #define HMC5883L_SAMPLES_2 0b01
79 | #define HMC5883L_SAMPLES_1 0b00
80 |
81 | #define QMC5883_CRA_AVERAGE_BIT 7
82 | #define QMC5883_CRA_AVERAGE_LENGTH 2
83 |
84 | #define QMC5883_SAMPLES_8 0b11
85 | #define QMC5883_SAMPLES_4 0b10
86 | #define QMC5883_SAMPLES_2 0b01
87 | #define QMC5883_SAMPLES_1 0b00
88 |
89 | // data rate
90 | #define HMC5883L_CRA_RATE_BIT 4
91 | #define HMC5883L_CRA_RATE_LENGTH 3
92 |
93 | #define HMC5883L_DATARATE_75HZ 0b110
94 | #define HMC5883L_DATARATE_30HZ 0b101
95 | #define HMC5883L_DATARATE_15HZ 0b100
96 | #define HMC5883L_DATARATE_7_5HZ 0b011
97 | #define HMC5883L_DATARATE_3HZ 0b010
98 | #define HMC5883L_DATARATE_1_5HZ 0b001
99 | #define HMC5883L_DATARATE_0_75_HZ 0b000
100 |
101 | #define QMC5883_CRA_RATE_BIT 3
102 | #define QMC5883_CRA_RATE_LENGTH 2
103 |
104 | #define QMC5883_DATARATE_10HZ 0b00
105 | #define QMC5883_DATARATE_50HZ 0b01
106 | #define QMC5883_DATARATE_100HZ 0b10
107 | #define QMC5883_DATARATE_200HZ 0b11
108 |
109 | // mode
110 | #define HMC5883L_MODEREG_BIT 1
111 | #define HMC5883L_MODEREG_LENGTH 2
112 |
113 | #define HMC5883L_MODE_IDLE 0b10
114 | #define HMC5883L_MODE_SINGLE 0b01
115 | #define HMC5883L_MODE_CONTINOUS 0b00
116 |
117 | #define QMC5883_MODEREG_BIT 1
118 | #define QMC5883_MODEREG_LENGTH 2
119 |
120 | #define QMC5883_MODE_STANDBY 0b00
121 | #define QMC5883_MODE_CONTINUOUS 0b01
122 |
123 | class Mag5883
124 | {
125 | public:
126 | Mag5883():isHMC_(false),isQMC_(false)
127 | {}
128 | bool initialize(void);
129 |
130 | bool testConnection();
131 |
132 | uint8_t getMeasurementBias();
133 | void setMeasurementBias(uint8_t bias);
134 |
135 | uint8_t getRange();
136 | void setRange(uint8_t gain);
137 |
138 | uint8_t getSampleAveraging();
139 | void setSampleAveraging(uint8_t averaging);
140 |
141 | uint8_t getDataRate();
142 | void setDataRate(uint8_t rate);
143 |
144 | uint8_t getMode();
145 | void setMode(uint8_t newMode);
146 |
147 | void getHeading(int16_t *x, int16_t *y, int16_t *z);
148 |
149 | int getICType(void);
150 | bool isHMC(){return isHMC_;}
151 | bool isQMC(){return isQMC_;}
152 | private:
153 | bool isHMC_;
154 | bool isQMC_;
155 | uint8_t mode;
156 | uint8_t buffer[6];
157 | };
158 |
159 | #endif
160 |
--------------------------------------------------------------------------------
/libhedrot/libhedrot_RTmagCalibration.h:
--------------------------------------------------------------------------------
1 | //
2 | // libhedrot_RTmagCalibration.h
3 | // hedrot_receiver
4 | //
5 | // Created by Alexis Baskind on 06/05/17.
6 | //
7 | // Part of code is derived from Matthieu Aussal, CMAP - Ecole Polytechnique / CNRS
8 | //
9 |
10 |
11 | #ifndef __hedrot_receiver__libhedrot_RTmagCalibration__
12 | #define __hedrot_receiver__libhedrot_RTmagCalibration__
13 |
14 | #include
15 | #include
16 | #define _USE_MATH_DEFINES // for C+Windows
17 | #include
18 | #include "libhedrot_utils.h"
19 | #include "libhedrot_calibration.h"
20 |
21 | #define M_GOLDEN_RATIO 1.61803398874989484820 // (1+sqrt(5))/2
22 | #define M_INV_GOLDEN_RATIO 0.61803398874989484820 // 1/M_GOLDEN_RATIO = M_GOLDEN_RATIO - 1
23 |
24 | #define RT_CAL_NUMBER_OF_ZONES 100 // number of zones in the unit sphere (defined by Fibonaci mapping)
25 | #define RT_CAL_NUMBER_OF_POINTS_PER_ZONE 100 // number of points per zone
26 |
27 | #define MAX_CONDITION_NUMBER_REALTIME 100000
28 |
29 | #define TIME_CONSTANT_INDICATOR_OF_REJECTED_POINTS 1600 // in samples
30 | #define MAX_ALLOWED_PROPORTION_OF_REJECTED_POINTS .5
31 |
32 | #define MAX_ALLOWED_STANDARD_DEVIATION_ERROR .1
33 |
34 | #define UPPER_NORM_FOR_ABSURD_VALUES 1.5 // for method RTmagCalibrationUpdateIterative
35 | #define UPPER_NORM2_FOR_ABSURD_VALUES UPPER_NORM_FOR_ABSURD_VALUES*UPPER_NORM_FOR_ABSURD_VALUES // for method RTmagCalibrationUpdateIterative
36 |
37 | //=====================================================================================================
38 | // structure definition: RTmagZoneData (structure that stores information per zone)
39 | //=====================================================================================================
40 | typedef struct _RTmagZoneData {
41 | short points[RT_CAL_NUMBER_OF_POINTS_PER_ZONE][3];
42 | double averagePoint[3];
43 | short numberOfPoints;
44 | short indexOfCurrentPoint;
45 | } RTmagZoneData;
46 |
47 | //=====================================================================================================
48 | // structure definition: RTmagCalData (structure that stores RT calibration data)
49 | //=====================================================================================================
50 | typedef struct _RTmagCalData {
51 | // parameters
52 | short calibrationRateFactor; // calibration rate
53 | char calibrationValid; // 0 => step 1 ("brute force" method), 1=> step 2 (with Fibonacci mapping)
54 | float RTmagMaxDistanceError;
55 |
56 | // for step 1 (with raw samples)
57 | long maxNumberOfSamples;
58 | long sampleIndexStep1; // internal
59 |
60 | // for step 2 (with Fibonacci mapping)
61 | float Fibonacci_Points[RT_CAL_NUMBER_OF_ZONES][3];
62 | RTmagZoneData *zoneData;
63 | float RTmagMinDistance2; //minimum squared distance error to accept or not a new point
64 | float RTmagMaxDistance2; //maximum squared distance error to accept or not a new point
65 | short numberOfFilledZones;
66 |
67 | // estimated values
68 | float estimatedOffset[3];
69 | float estimatedScaling[3], estimatedScalingFactor[3];
70 |
71 | // container for calibrating with ellipsoid fit and displaying purposes
72 | calibrationData* calData;
73 |
74 | // temporary container for storing data before filtering
75 | calibrationData* TMPcalData;
76 |
77 | // internal data
78 | short calibrationRateCounter;
79 | float proportionOfRejectedPoints_State;
80 | float proportionOfRejectedPoints_LPcoeff; // coefficient alpha of the low pass filter estimating the proportion of rejected points
81 | float previousEstimatedOffset[3], previousEstimatedScaling[3];
82 | float previousConditionNumber;
83 | } RTmagCalData;
84 |
85 | //=====================================================================================================
86 | // functions
87 | //=====================================================================================================
88 | RTmagCalData* newRTmagCalData();
89 | void freeRTmagCalData(RTmagCalData* data);
90 | void initRTmagCalData(RTmagCalData* data, float* initalEstimatedOffset, float* initalEstimatedScaling, float RTmagMaxDistanceError, short calibrationRateFactor, long maxNumberOfSamples);
91 |
92 | void RTmagCalibration_setCalibrationRateFactor(RTmagCalData* data, short calibrationRateFactor);
93 |
94 | void RTmagCalibration_setmaxNumberOfSamples(RTmagCalData* data, long maxNumberOfSamples);
95 |
96 | void RTmagCalibration_setRTmagMaxDistanceError(RTmagCalData* data, float RTmagMaxDistanceError);
97 |
98 | void computeFibonnaciMapping( RTmagCalData* data);
99 | short getClosestFibonacciPoint( RTmagCalData* data, double calPoint[3]);
100 | void addPoint2FibonnaciZone( RTmagCalData* data, short zoneNumber, short point[3]);
101 |
102 | short RTmagCalibrationUpdateDirect( RTmagCalData* data, short rawPoint[3]);
103 | short RTmagCalibrationUpdateIterative( RTmagCalData* data, short rawPoint[3]);
104 |
105 | #endif /* defined(__hedrot_receiver__libhedrot_RTmagCalibration__) */
106 |
--------------------------------------------------------------------------------
/matlab/calibration/ellipsoid_fit.m:
--------------------------------------------------------------------------------
1 | function [ center, radii, evecs, v ] = ellipsoid_fit( X, flag, equals )
2 | %
3 | % Fit an ellispoid/sphere to a set of xyz data points:
4 | %
5 | % [center, radii, evecs, pars ] = ellipsoid_fit( X )
6 | % [center, radii, evecs, pars ] = ellipsoid_fit( [x y z] );
7 | % [center, radii, evecs, pars ] = ellipsoid_fit( X, 1 );
8 | % [center, radii, evecs, pars ] = ellipsoid_fit( X, 2, 'xz' );
9 | % [center, radii, evecs, pars ] = ellipsoid_fit( X, 3 );
10 | %
11 | % Parameters:
12 | % * X, [x y z] - Cartesian data, n x 3 matrix or three n x 1 vectors
13 | % * flag - 0 fits an arbitrary ellipsoid (default),
14 | % - 1 fits an ellipsoid with its axes along [x y z] axes
15 | % - 2 followed by, say, 'xy' fits as 1 but also x_rad = y_rad
16 | % - 3 fits a sphere
17 | %
18 | % Output:
19 | % * center - ellispoid center coordinates [xc; yc; zc]
20 | % * ax - ellipsoid radii [a; b; c]
21 | % * evecs - ellipsoid radii directions as columns of the 3x3 matrix
22 | % * v - the 9 parameters describing the ellipsoid algebraically:
23 | % Ax^2 + By^2 + Cz^2 + 2Dxy + 2Exz + 2Fyz + 2Gx + 2Hy + 2Iz = 1
24 | %
25 | % Author:
26 | % Yury Petrov, Northeastern University, Boston, MA
27 | %
28 |
29 | error( nargchk( 1, 3, nargin ) ); % check input arguments
30 | if nargin == 1
31 | flag = 0; % default to a free ellipsoid
32 | end
33 | if flag == 2 && nargin == 2
34 | equals = 'xy';
35 | end
36 |
37 | if size( X, 2 ) ~= 3
38 | error( 'Input data must have three columns!' );
39 | else
40 | x = X( :, 1 );
41 | y = X( :, 2 );
42 | z = X( :, 3 );
43 | end
44 |
45 | % need nine or more data points
46 | if length( x ) < 9 && flag == 0
47 | error( 'Must have at least 9 points to fit a unique ellipsoid' );
48 | end
49 | if length( x ) < 6 && flag == 1
50 | error( 'Must have at least 6 points to fit a unique oriented ellipsoid' );
51 | end
52 | if length( x ) < 5 && flag == 2
53 | error( 'Must have at least 5 points to fit a unique oriented ellipsoid with two axes equal' );
54 | end
55 | if length( x ) < 3 && flag == 3
56 | error( 'Must have at least 4 points to fit a unique sphere' );
57 | end
58 |
59 | if flag == 0
60 | % fit ellipsoid in the form Ax^2 + By^2 + Cz^2 + 2Dxy + 2Exz + 2Fyz + 2Gx + 2Hy + 2Iz = 1
61 | D = [ x .* x, ...
62 | y .* y, ...
63 | z .* z, ...
64 | 2 * x .* y, ...
65 | 2 * x .* z, ...
66 | 2 * y .* z, ...
67 | 2 * x, ...
68 | 2 * y, ...
69 | 2 * z ]; % ndatapoints x 9 ellipsoid parameters
70 | elseif flag == 1
71 | % fit ellipsoid in the form Ax^2 + By^2 + Cz^2 + 2Gx + 2Hy + 2Iz = 1
72 | D = [ x .* x, ...
73 | y .* y, ...
74 | z .* z, ...
75 | 2 * x, ...
76 | 2 * y, ...
77 | 2 * z ]; % ndatapoints x 6 ellipsoid parameters
78 | elseif flag == 2
79 | % fit ellipsoid in the form Ax^2 + By^2 + Cz^2 + 2Gx + 2Hy + 2Iz = 1,
80 | % where A = B or B = C or A = C
81 | if strcmp( equals, 'yz' ) || strcmp( equals, 'zy' )
82 | D = [ y .* y + z .* z, ...
83 | x .* x, ...
84 | 2 * x, ...
85 | 2 * y, ...
86 | 2 * z ];
87 | elseif strcmp( equals, 'xz' ) || strcmp( equals, 'zx' )
88 | D = [ x .* x + z .* z, ...
89 | y .* y, ...
90 | 2 * x, ...
91 | 2 * y, ...
92 | 2 * z ];
93 | else
94 | D = [ x .* x + y .* y, ...
95 | z .* z, ...
96 | 2 * x, ...
97 | 2 * y, ...
98 | 2 * z ];
99 | end
100 | else
101 | % fit sphere in the form A(x^2 + y^2 + z^2) + 2Gx + 2Hy + 2Iz = 1
102 | D = [ x .* x + y .* y + z .* z, ...
103 | 2 * x, ...
104 | 2 * y, ...
105 | 2 * z ]; % ndatapoints x 4 sphere parameters
106 | end
107 |
108 | % solve the normal system of equations
109 | v = ( D' * D ) \ ( D' * ones( size( x, 1 ), 1 ) );
110 |
111 | % find the ellipsoid parameters
112 | if flag == 0
113 | % form the algebraic form of the ellipsoid
114 | A = [ v(1) v(4) v(5) v(7); ...
115 | v(4) v(2) v(6) v(8); ...
116 | v(5) v(6) v(3) v(9); ...
117 | v(7) v(8) v(9) -1 ];
118 | % find the center of the ellipsoid
119 | center = -A( 1:3, 1:3 ) \ [ v(7); v(8); v(9) ];
120 | % form the corresponding translation matrix
121 | T = eye( 4 );
122 | T( 4, 1:3 ) = center';
123 | % translate to the center
124 | R = T * A * T';
125 | % solve the eigenproblem
126 | [ evecs evals ] = eig( R( 1:3, 1:3 ) / -R( 4, 4 ) );
127 | radii = sqrt( 1 ./ diag( evals ) );
128 | else
129 | if flag == 1
130 | v = [ v(1) v(2) v(3) 0 0 0 v(4) v(5) v(6) ];
131 | elseif flag == 2
132 | if strcmp( equals, 'xz' ) || strcmp( equals, 'zx' )
133 | v = [ v(1) v(2) v(1) 0 0 0 v(3) v(4) v(5) ];
134 | elseif strcmp( equals, 'yz' ) || strcmp( equals, 'zy' )
135 | v = [ v(2) v(1) v(1) 0 0 0 v(3) v(4) v(5) ];
136 | else % xy
137 | v = [ v(1) v(1) v(2) 0 0 0 v(3) v(4) v(5) ];
138 | end
139 | else
140 | v = [ v(1) v(1) v(1) 0 0 0 v(2) v(3) v(4) ];
141 | end
142 | center = ( -v( 7:9 ) ./ v( 1:3 ) )';
143 | gam = 1 + ( v(7)^2 / v(1) + v(8)^2 / v(2) + v(9)^2 / v(3) );
144 | radii = ( sqrt( gam ./ v( 1:3 ) ) )';
145 | evecs = eye( 3 );
146 | end
147 |
148 |
149 |
--------------------------------------------------------------------------------
/scripts/Win/makeDistribution.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | echo This script builds a 64 bit windows distribution of hedrot (including however the 32 bit version of the max object).
3 | echo Before running this script, be sure that:
4 | echo 1/ all binaries have been compiled
5 | echo 2/ a pdf version of the doc has been created
6 | echo 3/ the Max standalone hedrotReceiver has been built.
7 |
8 | set today=%date:~-2%-%date:~3,2%-%date:~0,2%
9 |
10 | set thisDirectory=%cd%
11 | set "rootDirectory=%thisDirectory%\..\.."
12 | set "destDirectory=%rootDirectory%\build\forPackaging"
13 |
14 | set "testfile=%rootDirectory%\libhedrot\libhedrot.h"
15 | awk "/\#define HEDROT_VERSION / { print $3 }" %testfile% > tmp.txt
16 | sed -i 's/"//g' tmp.txt
17 | set /p hedrotVersion= tmp.txt
24 | sed -i 's/"//g' tmp.txt
25 | set /p hedrotFirmwareVersion= nul
43 |
44 | REM ######### copy the command-line-demo #############################
45 | md "%packageFolder%\command-line-demo"
46 | copy "%rootDirectory%\command-line-demo\visual studio\exe\Release_x64\hedrotReceiverDemo.exe" "%packageFolder%\command-line-demo\" > nul
47 |
48 | REM ######### copy the firmware (both versions) #############################
49 | md "%packageFolder%\firmware"
50 | copy "%rootDirectory%\firmware\hex\hedrot-firmware-teensy31-32.ino.hex" "%packageFolder%\firmware\hedrot-firmware-teensy31-32_version_%hedrotFirmwareVersion%.hex" > nul
51 | copy "%rootDirectory%\firmware\hex\hedrot-firmware-teensyLC.ino.hex" "%packageFolder%\firmware\hedrot-firmware-teensyLC_version_%hedrotFirmwareVersion%.hex" > nul
52 | copy "%rootDirectory%\firmware\CHANGELOG.txt" "%packageFolder%\firmware\" > nul
53 |
54 | REM ######### copy the max source code and external #############################
55 | md "%packageFolder%\Max"
56 | copy "%rootDirectory%\hedrotReceiver\hedrotReceiver.json" "%packageFolder%\Max\" > nul
57 | copy "%rootDirectory%\hedrotReceiver\patches\*.maxpat" "%packageFolder%\Max\" > nul
58 | copy "%rootDirectory%\hedrotReceiver\hedrot_receiver.mxe" "%packageFolder%\Max\" > nul
59 | copy "%rootDirectory%\hedrotReceiver\hedrot_receiver.mxe64" "%packageFolder%\Max\" > nul
60 |
61 | REM ######### copy the examples folder #############################
62 | md "%packageFolder%\examples"
63 | xcopy "%rootDirectory%\examples" "%packageFolder%\examples" /Y /Q /i /s
64 |
65 | REM ######### copy the dll folder #############################
66 | md "%packageFolder%\dll"
67 | xcopy "%rootDirectory%\dll" "%packageFolder%\dll" /Y /Q /i /s
68 |
69 | REM ######### copy the doc #############################
70 | copy "%rootDirectory%\doc\hedrot user manual.pdf" "%packageFolder%" > nul
71 |
72 | REM ######### copy the license file #############################
73 | copy "%rootDirectory%\LICENSE" "%packageFolder%" > nul
74 |
75 | REM ######### copy the CHANGELOG.txt file #############################
76 | copy "%rootDirectory%\CHANGELOG.txt" "%packageFolder%" > nul
77 |
78 | REM ######### copy and update the main README.txt file #############################
79 | copy "%rootDirectory%\scripts\README-DISTRIBUTION.txt" "%packageFolder%\README.txt" > nul
80 | sed -i "s/Hedrot Version: XXXX/Hedrot Version: %hedrotVersion%/g;" %packageFolder%\README.txt
81 | sed -i "s/Firmware Version: YYYY/Firmware Version: %hedrotFirmwareVersion%/g;" %packageFolder%\README.txt
82 |
83 | REM ######### change the icon of the standalone folder and of the standalone #############################
84 | C:\Users\Baskind\Desktop\Developpement\utils\rcedit "%packageFolder%\hedrotReceiver\hedrotReceiver.exe" --set-icon %thisDirectory%\..\logo\hedrot.ico
85 | cd %packageFolder%
86 | echo [.ShellClassInfo] >> hedrotReceiver\desktop.ini
87 | echo IconResource=%thisDirectory%\..\logo\hedrot.ico >> hedrotReceiver\desktop.ini
88 | echo [ViewState] >> hedrotReceiver\desktop.ini
89 | echo Mode= >> hedrotReceiver\desktop.ini
90 | echo Vid= >> hedrotReceiver\desktop.ini
91 | echo FolderType=Documents >> hedrotReceiver\desktop.ini
92 | attrib -A +S +H hedrotReceiver\desktop.ini
93 | attrib +R hedrotReceiver
94 |
95 | REM ######### ZIP #############################
96 |
97 | REM #erase the ZIP if it exists
98 | del "%rootDirectory%\build\%packageName%.zip"
99 |
100 | REM #create the ZIP
101 | cd "%destDirectory%\tmpPackageFolder\%packageName%"
102 | 7z a -r -tzip "%rootDirectory%\build\%packageName%.zip" * > nul
103 |
104 | REM #erase temp build directory
105 | cd %destDirectory%
106 | rmdir /s /q "%destDirectory%\tmpPackageFolder"
107 |
108 | cd %thisDirectory%
--------------------------------------------------------------------------------
/firmware/hedrot-firmware/ITG3200.h:
--------------------------------------------------------------------------------
1 | // ITG3200.cpp: ITG3200 I2C device methods
2 | // based on I2Cdev library collection - ITG3200 I2C device class
3 | // adapted for i2c_t3 through the custom code I2Ccom.cpp
4 |
5 |
6 | #ifndef _ITG3200_H_
7 | #define _ITG3200_H_
8 |
9 | #include "I2Ccom.h"
10 |
11 | #define ITG3200_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for SparkFun IMU Digital Combo board
12 | #define ITG3200_ADDRESS_AD0_HIGH 0x69 // address pin high (VCC), default for SparkFun ITG-3200 Breakout board
13 | #define ITG3200_DEFAULT_ADDRESS ITG3200_ADDRESS_AD0_LOW
14 |
15 | #define ITG3200_RA_WHO_AM_I 0x00
16 | #define ITG3200_RA_SMPLRT_DIV 0x15
17 | #define ITG3200_RA_DLPF_FS 0x16
18 | #define ITG3200_RA_INT_CFG 0x17
19 | #define ITG3200_RA_INT_STATUS 0x1A
20 | #define ITG3200_RA_TEMP_OUT_H 0x1B
21 | #define ITG3200_RA_TEMP_OUT_L 0x1C
22 | #define ITG3200_RA_GYRO_XOUT_H 0x1D
23 | #define ITG3200_RA_GYRO_XOUT_L 0x1E
24 | #define ITG3200_RA_GYRO_YOUT_H 0x1F
25 | #define ITG3200_RA_GYRO_YOUT_L 0x20
26 | #define ITG3200_RA_GYRO_ZOUT_H 0x21
27 | #define ITG3200_RA_GYRO_ZOUT_L 0x22
28 | #define ITG3200_RA_PWR_MGM 0x3E
29 |
30 | #define ITG3200_DEVID_BIT 6
31 | #define ITG3200_DEVID_LENGTH 6
32 |
33 | #define ITG3200_DF_FS_SEL_BIT 4
34 | #define ITG3200_DF_FS_SEL_LENGTH 2
35 | #define ITG3200_DF_DLPF_CFG_BIT 2
36 | #define ITG3200_DF_DLPF_CFG_LENGTH 3
37 |
38 | #define ITG3200_FULLSCALE_2000 0x03
39 |
40 | #define ITG3200_DLPF_BW_256 0x00
41 | #define ITG3200_DLPF_BW_188 0x01
42 | #define ITG3200_DLPF_BW_98 0x02
43 | #define ITG3200_DLPF_BW_42 0x03
44 | #define ITG3200_DLPF_BW_20 0x04
45 | #define ITG3200_DLPF_BW_10 0x05
46 | #define ITG3200_DLPF_BW_5 0x06
47 |
48 | #define ITG3200_INTCFG_ACTL_BIT 7
49 | #define ITG3200_INTCFG_OPEN_BIT 6
50 | #define ITG3200_INTCFG_LATCH_INT_EN_BIT 5
51 | #define ITG3200_INTCFG_INT_ANYRD_2CLEAR_BIT 4
52 | #define ITG3200_INTCFG_ITG_RDY_EN_BIT 2
53 | #define ITG3200_INTCFG_RAW_RDY_EN_BIT 0
54 |
55 | #define ITG3200_INTMODE_ACTIVEHIGH 0x00
56 | #define ITG3200_INTMODE_ACTIVELOW 0x01
57 |
58 | #define ITG3200_INTDRV_PUSHPULL 0x00
59 | #define ITG3200_INTDRV_OPENDRAIN 0x01
60 |
61 | #define ITG3200_INTLATCH_50USPULSE 0x00
62 | #define ITG3200_INTLATCH_WAITCLEAR 0x01
63 |
64 | #define ITG3200_INTCLEAR_STATUSREAD 0x00
65 | #define ITG3200_INTCLEAR_ANYREAD 0x01
66 |
67 | #define ITG3200_INTSTAT_ITG_RDY_BIT 2
68 | #define ITG3200_INTSTAT_RAW_DATA_READY_BIT 0
69 |
70 | #define ITG3200_PWR_H_RESET_BIT 7
71 | #define ITG3200_PWR_SLEEP_BIT 6
72 | #define ITG3200_PWR_STBY_XG_BIT 5
73 | #define ITG3200_PWR_STBY_YG_BIT 4
74 | #define ITG3200_PWR_STBY_ZG_BIT 3
75 | #define ITG3200_PWR_CLK_SEL_BIT 2
76 | #define ITG3200_PWR_CLK_SEL_LENGTH 3
77 |
78 | #define ITG3200_CLOCK_INTERNAL 0x00
79 | #define ITG3200_CLOCK_PLL_XGYRO 0x01
80 | #define ITG3200_CLOCK_PLL_YGYRO 0x02
81 | #define ITG3200_CLOCK_PLL_ZGYRO 0x03
82 | #define ITG3200_CLOCK_PLL_EXT32K 0x04
83 | #define ITG3200_CLOCK_PLL_EXT19M 0x05
84 |
85 | class ITG3200 {
86 | public:
87 | ITG3200();
88 | ITG3200(uint8_t address);
89 |
90 | void initialize();
91 | bool testConnection();
92 |
93 | // WHO_AM_I register
94 | uint8_t getDeviceID();
95 | void setDeviceID(uint8_t id);
96 |
97 | // SMPLRT_DIV register
98 | uint8_t getRate();
99 | void setRate(uint8_t rate);
100 |
101 | // DLPF_FS register
102 | uint8_t getFullScaleRange();
103 | void setFullScaleRange(uint8_t range);
104 | uint8_t getDLPFBandwidth();
105 | void setDLPFBandwidth(uint8_t bandwidth);
106 |
107 | // INT_CFG register
108 | bool getInterruptMode();
109 | void setInterruptMode(bool mode);
110 | bool getInterruptDrive();
111 | void setInterruptDrive(bool drive);
112 | bool getInterruptLatch();
113 | void setInterruptLatch(bool latch);
114 | bool getInterruptLatchClear();
115 | void setInterruptLatchClear(bool clear);
116 | bool getIntDeviceReadyEnabled();
117 | void setIntDeviceReadyEnabled(bool enabled);
118 | bool getIntDataReadyEnabled();
119 | void setIntDataReadyEnabled(bool enabled);
120 |
121 | // INT_STATUS register
122 | bool getIntDeviceReadyStatus();
123 | bool getIntDataReadyStatus();
124 |
125 | // TEMP_OUT_* registers
126 | int16_t getTemperature();
127 |
128 | // GYRO_*OUT_* registers
129 | void getRotation(int16_t* x, int16_t* y, int16_t* z);
130 | int16_t getRotationX();
131 | int16_t getRotationY();
132 | int16_t getRotationZ();
133 |
134 | // PWR_MGM register
135 | void reset();
136 | bool getSleepEnabled();
137 | void setSleepEnabled(bool enabled);
138 | bool getStandbyXEnabled();
139 | void setStandbyXEnabled(bool enabled);
140 | bool getStandbyYEnabled();
141 | void setStandbyYEnabled(bool enabled);
142 | bool getStandbyZEnabled();
143 | void setStandbyZEnabled(bool enabled);
144 | uint8_t getClockSource();
145 | void setClockSource(uint8_t source);
146 |
147 | private:
148 | uint8_t devAddr;
149 | uint8_t buffer[6];
150 | };
151 |
152 | #endif /* _ITG3200_H_ */
153 |
--------------------------------------------------------------------------------
/command-line-demo/source/hedrotReceiverDemo.c:
--------------------------------------------------------------------------------
1 | //
2 | // hedrotReceiverDemo_cmd.c
3 | //
4 | // Created by Alexis Baskind on 16/10/16.
5 | // Copyright (c) 2016 Alexis Baskind. All rights reserved.
6 | //
7 |
8 | #include
9 |
10 | #include "libhedrot.h"
11 | #include "hedrot_comm_protocol.h"
12 |
13 | // time constants
14 | #define TICK_PERIOD .1 // time period in seconds between two ticks
15 |
16 | //=====================================================================================================
17 | // definitions and includes for clocking
18 | //=====================================================================================================
19 | #ifdef __MACH__ // if mach (mac os X)
20 | #include
21 | #include
22 | double getTime() {
23 | clock_serv_t cclock;
24 | mach_timespec_t mts;
25 | host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
26 | clock_get_time(cclock, &mts);
27 | mach_port_deallocate(mach_task_self(), cclock);
28 | return mts.tv_sec + mts.tv_nsec*1e-9;
29 | }
30 | #else
31 | #if defined(_WIN32) || defined(_WIN64)
32 | #include
33 | double getTime() {
34 | LARGE_INTEGER frequency;
35 | LARGE_INTEGER time;
36 | QueryPerformanceFrequency(&frequency);
37 | QueryPerformanceCounter(&time);
38 | return time.QuadPart / (double)frequency.QuadPart;
39 | }
40 | #endif /* #if defined(_WIN32) || defined(_WIN64) */
41 | #endif /* #ifdef __MACH__ */
42 |
43 |
44 | int main(int argc, const char * argv[]) {
45 | double currentTime1, currentTime2, previousTime;
46 | char messageNumber;
47 | int i;
48 |
49 | headtrackerData* trackingData;
50 |
51 | printf("Hedrot command-line demo, based on hedrot version %s, compiled on "__DATE__"\r\n", HEDROT_VERSION);
52 | printf("Required firmware version %d\r\n", HEDROT_FIRMWARE_VERSION);
53 |
54 | trackingData = headtracker_new();
55 |
56 | // change baudrate (for some reason the command-line version does not accept higher baud rates than 57600)
57 | trackingData->serialcomm->baud = 57600;
58 |
59 | // set verbose to 1
60 | setVerbose(trackingData,1);
61 |
62 | // set autodiscover to 1
63 | setAutoDiscover(trackingData,1);
64 |
65 | // switch on the headtracker
66 | setHeadtrackerOn(trackingData,1);
67 | //headtracker_open(trackingData,1); // if autodiscover = 0
68 |
69 | previousTime = getTime();
70 |
71 | while(1) { //infinite loop
72 | currentTime1 = getTime();
73 |
74 | // next tick
75 | headtracker_tick(trackingData);
76 |
77 | // process messages to notify
78 | while( (messageNumber = pullNotificationMessage(trackingData)) ) {
79 | switch( messageNumber ) {
80 | case NOTIFICATION_MESSAGE_COMM_PORT_LIST_UPDATED:
81 | printf("port list updated, %d ports found\r\n", trackingData->serialcomm->numberOfAvailablePorts);
82 | for(i = 0;iserialcomm->numberOfAvailablePorts; i++) {
83 | printf("\t port %d: %s \r\n", i, trackingData->serialcomm->availablePorts[i]);
84 | }
85 | break;
86 | case NOTIFICATION_MESSAGE_PORT_OPENED:
87 | printf("port %s opened\r\n", trackingData->serialcomm->availablePorts[trackingData->serialcomm->portNumber]);
88 | break;
89 | case NOTIFICATION_MESSAGE_WRONG_FIRMWARE_VERSION:
90 | printf("Wrong Headtracker Firmware Version - expected version: %i - actual version: %i\r\n",HEDROT_FIRMWARE_VERSION,trackingData->firmwareVersion);
91 | break;
92 | case NOTIFICATION_MESSAGE_HEADTRACKER_STATUS_CHANGED:
93 | printf("new reception status: %d\r\n",trackingData->infoReceptionStatus);
94 | break;
95 | case NOTIFICATION_MESSAGE_SETTINGS_DATA_READY:
96 | printf("headtracking settings received\r\n");
97 | break;
98 | case NOTIFICATION_MESSAGE_CALIBRATION_NOT_VALID:
99 | printf("calibration not valid\r\n");
100 | break;
101 | case NOTIFICATION_MESSAGE_GYRO_CALIBRATION_STARTED:
102 | printf("gyroscope calibration started\r\n");
103 | break;
104 | case NOTIFICATION_MESSAGE_GYRO_CALIBRATION_FINISHED:
105 | printf("gyroscope calibration finished\r\n");
106 | break;
107 | case NOTIFICATION_MESSAGE_BOARD_OVERLOAD:
108 | printf("board too slow, reduce samplerate\r\n");
109 | break;
110 | }
111 | }
112 | currentTime2 = getTime();
113 |
114 |
115 | // print estimated quaternion and angles if transmitting
116 | if(trackingData->infoReceptionStatus == COMMUNICATION_STATE_HEADTRACKER_TRANSMITTING) {
117 | printf("estimated quaternion: %f %f %f %f\r\n", trackingData->qcent1, trackingData->qcent2, trackingData->qcent3, trackingData->qcent4);
118 | printf("estimated angles: yaw %f - pitch %f - roll %f\r\n", trackingData->yaw, trackingData->pitch, trackingData->roll);
119 | printf("Time elapsed since last tick = %f sec\r\n", currentTime2 - previousTime);
120 | }
121 |
122 | previousTime = currentTime2;
123 |
124 | // sleep so that the next tick starts TICK_PERIOD later
125 | #if defined(_WIN32) || defined(_WIN64)
126 | Sleep((DWORD) (TICK_PERIOD*1000));
127 | #else /* #if defined(_WIN32) || defined(_WIN64) */
128 | usleep((int) ((TICK_PERIOD + currentTime2 - currentTime1) * 1000000));
129 | #endif /* #if defined(_WIN32) || defined(_WIN64) */
130 | }
131 |
132 | return 0;
133 | }
134 |
--------------------------------------------------------------------------------
/libhedrot/libhedrot_utils.c:
--------------------------------------------------------------------------------
1 | //
2 | // libhedrot_utils.c
3 | // hedrot_receiver
4 | //
5 | // Created by Alexis Baskind on 17/04/17.
6 | //
7 | //
8 |
9 | #include
10 | #include
11 | #if defined(_WIN32) || defined(_WIN64)
12 | #include
13 | #endif
14 | #include "libhedrot_utils.h"
15 |
16 |
17 |
18 | //=====================================================================================================
19 | // utils
20 | //=====================================================================================================
21 |
22 | // double floating point modulo
23 | double mod(double a, double N) {return a - N*floor(a/N);} //return in range [0, N]
24 |
25 | // round (not defined in VS2012)
26 | #if defined(_WIN32) || defined(_WIN64)
27 | double round(double value) {
28 | return value < 0 ? -floor(0.5 - value) : floor(0.5 + value);
29 | }
30 | #endif /* #if defined(_WIN32) || defined(_WIN64) */
31 |
32 |
33 |
34 | //---------------------------------------------------------------------------------------------------
35 | // Fast inverse square-root
36 |
37 | // single precision version
38 | // See: http://en.wikipedia.org/wiki/Fast_inverse_square_root
39 | float invSqrt(float x) {
40 | float halfx = 0.5f * x;
41 | float y = x;
42 | int32_t i = *(int32_t*)&y;
43 | i = 0x5f3759df - (i>>1);
44 | y = *(float*)&i;
45 | y = y * (1.5f - (halfx * y * y));
46 | return y;
47 | }
48 |
49 |
50 | /* double precision version
51 | // See: https://tbach.web.cern.ch/tbach/thesis/literature/fastinvsquare_robertson.pdf
52 | double invSqrt(double x) {
53 | uint64_t i;
54 | double x2, y;
55 | x2 = x * 0.5;
56 | y = x;
57 | i = *(uint64_t *) &y;
58 | i = 0x5fe6eb50c7b537a9 - (i >> 1);
59 | y = *(double *) &i;
60 | y = y * (1.5 - (x2 * y * y));
61 | return y;
62 | }
63 | */
64 |
65 | /*
66 | // not optimized (but more precise) version
67 | double invSqrt(double x) {
68 | if(x==0) return 1e40; // arbitrary very big number
69 | else return 1./sqrt(x);
70 | }*/
71 |
72 | void quaternion2YawPitchRoll(float q1, float q2, float q3, float q4, float *yaw, float *pitch, float *roll) {
73 | // zyx Talt-Bryan rotation sequence
74 |
75 | *yaw = (float) (RAD_TO_DEGREE * atan2(2.0f * (q1*q4 + q2*q3),
76 | 1.0f - 2.0f * (q3*q3 + q4*q4) ));
77 |
78 | *pitch = (float) (RAD_TO_DEGREE * asin(min(max(2.0f * (q1*q3 - q4*q2),-1),1)));
79 |
80 |
81 | *roll= (float) (RAD_TO_DEGREE * atan2(2.0f * (q1*q2 + q3*q4),
82 | 1.0f - 2.0f * (q2*q2 + q3*q3)));
83 | }
84 |
85 | void quaternion2RollPitchYaw(float q1, float q2, float q3, float q4, float *yaw, float *pitch, float *roll) {
86 | // xyz Talt-Bryan rotation sequence
87 |
88 | *roll = (float) (RAD_TO_DEGREE * atan2(2.0f * (q1*q2 - q3*q4),
89 | 1.0f - 2.0f * (q2*q2 + q3*q3) ));
90 |
91 | *pitch = (float) (RAD_TO_DEGREE * asin(min(max(2.0f * (q1*q3 + q4*q2),-1),1)));
92 |
93 |
94 | *yaw= (float) (RAD_TO_DEGREE * atan2(2.0f * (q1*q4 - q2*q3),
95 | 1.0f - 2.0f * (q3*q3 + q4*q4)));
96 | }
97 |
98 | void quaternionComposition(float q01, float q02, float q03, float q04, float q11, float q12, float q13, float q14, float *q21, float *q22, float *q23, float *q24) {
99 | // compose two quaternions (Hamilton product)
100 | // the quaternion (q11, q12, q13, q14) is rotated according to the reference quaternion (q01, q02, q03, q04)
101 | *q21 = q01 * q11 - q02 * q12 - q03 * q13 - q04 * q14;
102 | *q22 = q01 * q12 + q02 * q11 + q03 * q14 - q04 * q13;
103 | *q23 = q01 * q13 - q02 * q14 + q03 * q11 + q04 * q12;
104 | *q24 = q01 * q14 + q02 * q13 - q03 * q12 + q04 * q11;
105 | }
106 |
107 | int stringToFloats(char* valueBuffer, float* data, int nvalues) {
108 | int i=0;
109 |
110 | char *delim = " "; // input separated by spaces
111 | char *token = NULL;
112 | char *brkt;
113 |
114 | for (token = strtok_r(valueBuffer, delim, &brkt); token != NULL; token = strtok_r(NULL, delim, &brkt))
115 | {
116 | char *unconverted;
117 | data[i] = (float) strtod(token, &unconverted);
118 | i++;
119 | }
120 |
121 | if(i
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Debug
10 | x64
11 |
12 |
13 | Release
14 | Win32
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {F51F214F-1832-4CF4-ACC5-1A6AB701C4CC}
23 | Win32Proj
24 | hedrotReceiverDemo
25 |
26 |
27 |
28 | Application
29 | true
30 | v110
31 | MultiByte
32 |
33 |
34 | Application
35 | true
36 | v110
37 | MultiByte
38 |
39 |
40 | Application
41 | false
42 | v110
43 | true
44 | MultiByte
45 |
46 |
47 | Application
48 | false
49 | v110
50 | true
51 | MultiByte
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | true
71 | true
72 | build\$(Configuration)_$(PlatformName)\
73 | exe\$(Configuration)_$(PlatformName)\
74 |
75 |
76 | true
77 | true
78 | build\$(Configuration)_$(PlatformName)\
79 | exe\$(Configuration)_$(PlatformName)\
80 |
81 |
82 | false
83 | build\$(Configuration)_$(PlatformName)\
84 | exe\$(Configuration)_$(PlatformName)\
85 |
86 |
87 | false
88 | build\$(Configuration)_$(PlatformName)\
89 | exe\$(Configuration)_$(PlatformName)\
90 |
91 |
92 |
93 | NotUsing
94 | Level3
95 | Disabled
96 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
97 | true
98 | ..\..\firmware\hedrot-firmware;..\..\libhedrot;%(AdditionalIncludeDirectories)
99 |
100 |
101 | Console
102 | true
103 |
104 |
105 |
106 |
107 | NotUsing
108 | Level3
109 | Disabled
110 | ADD_;HAVE_LAPACK_CONFIG_H;LAPACK_COMPLEX_STRUCTURE;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
111 | true
112 | ..\..\firmware\hedrot-firmware;..\..\libhedrot;C:\Users\Baskind\Desktop\Developpement\libraries\lapack-3.7.0-lib\include;%(AdditionalIncludeDirectories)
113 |
114 |
115 | Console
116 | true
117 | C:\Users\Baskind\Desktop\Developpement\libraries\lapack-3.7.0-lib\lib
118 | libblas.dll.a;liblapack.dll.a;liblapacke.dll.a;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
119 |
120 |
121 |
122 |
123 | Level3
124 |
125 |
126 | MaxSpeed
127 | true
128 | true
129 | ADD_;HAVE_LAPACK_CONFIG_H;LAPACK_COMPLEX_STRUCTURE;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
130 | true
131 | C:\Users\Baskind\Desktop\Developpement\libraries\lapack-3.7.0-lib\include;..\..\firmware\hedrot-firmware;..\..\libhedrot;%(AdditionalIncludeDirectories)
132 |
133 |
134 | Console
135 | true
136 | true
137 | true
138 | libblas.lib;liblapack.lib;liblapacke.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
139 | C:\Users\Baskind\Desktop\Developpement\libraries\lapack for windows\dll\win32
140 |
141 |
142 |
143 |
144 | Level3
145 |
146 |
147 | MaxSpeed
148 | true
149 | true
150 | ADD_;HAVE_LAPACK_CONFIG_H;LAPACK_COMPLEX_STRUCTURE;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
151 | true
152 | ..\..\firmware\hedrot-firmware;..\..\libhedrot;C:\Users\Baskind\Desktop\Developpement\libraries\lapack-3.7.0-lib\include;%(AdditionalIncludeDirectories)
153 | ProgramDatabase
154 |
155 |
156 | Console
157 | true
158 | true
159 | true
160 | libblas.dll.a;liblapack.dll.a;liblapacke.dll.a;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
161 | C:\Users\Baskind\Desktop\Developpement\libraries\lapack-3.7.0-lib\lib
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
--------------------------------------------------------------------------------
/firmware/hedrot-firmware/Mag5883.cpp:
--------------------------------------------------------------------------------
1 | // Mag5883.cpp: Mag5883 I2C device methods for both Magnetometers used in gy-85 boards:
2 | // . Honeywell HMC5883L
3 | // . QMC5883L
4 | // part of code derived from [DFRobot](http://www.dfrobot.com), 2017
5 | // part of code derived from I2Cdev library
6 |
7 | #include "Mag5883.h"
8 |
9 | bool Mag5883::initialize()
10 | {
11 | int retry;
12 | retry = 5;
13 |
14 | while(retry--){
15 | Wire.beginTransmission(HMC5883L_ADDRESS);
16 | isHMC_ = (0 == Wire.endTransmission());
17 | if(isHMC_){
18 | break;
19 | }
20 | delay(20);
21 | }
22 | //Serial.print("isHMC_= ");
23 | //Serial.println(isHMC_);
24 |
25 | if(isHMC_){
26 | if ((readByte(HMC5883L_ADDRESS, HMC5883L_REG_IDENT_A) != 0x48)
27 | || (readByte(HMC5883L_ADDRESS, HMC5883L_REG_IDENT_B) != 0x34)
28 | || (readByte(HMC5883L_ADDRESS, HMC5883L_REG_IDENT_C) != 0x33)){
29 | return false;
30 | }
31 |
32 | setMeasurementBias(HMC5883L_BIAS_NORMAL);
33 | setRange(HMC5883L_RANGE_0_88G);
34 | setMode(HMC5883L_MODE_SINGLE);
35 | setDataRate(HMC5883L_DATARATE_75HZ);
36 | setSampleAveraging(HMC5883L_SAMPLES_1);
37 |
38 | return true;
39 | }else{
40 | retry = 5;
41 | while(retry--){
42 | Wire.begin();
43 | Wire.beginTransmission(QMC5883_ADDRESS);
44 | isQMC_ = (0 == Wire.endTransmission());
45 | if(isHMC_){
46 | break;
47 | }
48 | delay(20);
49 | }
50 | //Serial.print("isQMC_= ");
51 | //Serial.println(isQMC_);
52 | if(isQMC_){
53 | writeByte(QMC5883_ADDRESS, QMC5883_REG_IDENT_B, 0X01);
54 | writeByte(QMC5883_ADDRESS, QMC5883_REG_IDENT_C, 0X40);
55 | writeByte(QMC5883_ADDRESS, QMC5883_REG_IDENT_D, 0X01);
56 | writeByte(QMC5883_ADDRESS, QMC5883_REG_CONFIG_1, 0X1D);
57 |
58 | if ((readByte(QMC5883_ADDRESS, QMC5883_REG_IDENT_B) != 0x01)
59 | || (readByte(QMC5883_ADDRESS, QMC5883_REG_IDENT_C) != 0x40)
60 | || (readByte(QMC5883_ADDRESS, QMC5883_REG_IDENT_D) != 0x01)){
61 | return false;
62 | }
63 | setRange(QMC5883_RANGE_8G);
64 | setMode(QMC5883_MODE_CONTINUOUS);
65 | setDataRate(QMC5883_DATARATE_200HZ);
66 | setSampleAveraging(QMC5883_SAMPLES_1);
67 |
68 | return true;
69 | }
70 | }
71 | return false;
72 | }
73 |
74 | /** Verify the I2C connection.
75 | * Make sure the device is connected and responds as expected.
76 | * @return True if connection is valid, false otherwise
77 | */
78 | bool Mag5883::testConnection() {
79 | if(isHMC_){
80 | return ((readByte(HMC5883L_ADDRESS, HMC5883L_REG_IDENT_A) == 0x48)
81 | && (readByte(HMC5883L_ADDRESS, HMC5883L_REG_IDENT_B) == 0x34)
82 | && (readByte(HMC5883L_ADDRESS, HMC5883L_REG_IDENT_C) == 0x33));
83 | } else {
84 | return ((readByte(QMC5883_ADDRESS, QMC5883_REG_IDENT_B) == 0x01)
85 | && (readByte(QMC5883_ADDRESS, QMC5883_REG_IDENT_C) == 0x40)
86 | && (readByte(QMC5883_ADDRESS, QMC5883_REG_IDENT_D) == 0x01));
87 | }
88 | }
89 |
90 | /** Get measurement bias value.
91 | * This function has no effect sif QMC5883
92 | @return if HMC5883L: Current bias value (0-2 for normal/positive/negative respectively). If QMC5883 (0)
93 | */
94 | uint8_t Mag5883::getMeasurementBias() {
95 | if(isHMC_){
96 | return readBits(HMC5883L_ADDRESS, HMC5883L_REG_CONFIG_A, HMC5883L_CRA_BIAS_BIT, HMC5883L_CRA_BIAS_LENGTH);
97 | } else {
98 | return 0; // no effect
99 | }
100 | }
101 |
102 | /** Set measurement bias value.
103 | * This function has no effect if QMC5883
104 | @@param bias if HMC5883L: New bias value (0-2 for normal/positive/negative respectively)
105 | */
106 | void Mag5883::setMeasurementBias(uint8_t bias) {
107 | if(isHMC_){
108 | writeBits(HMC5883L_ADDRESS, HMC5883L_REG_CONFIG_A, HMC5883L_CRA_BIAS_BIT, HMC5883L_CRA_BIAS_LENGTH, bias);
109 | } else {
110 | //do nothing
111 | }
112 | }
113 |
114 | /** Get number of samples averaged per measurement.
115 | * @return Current samples averaged per measurement (0-3 for 1/2/4/8 respectively)
116 | */
117 | uint8_t Mag5883::getSampleAveraging() {
118 | if(isHMC_){
119 | return readBits(HMC5883L_ADDRESS, HMC5883L_REG_CONFIG_A, HMC5883L_CRA_AVERAGE_BIT, HMC5883L_CRA_AVERAGE_LENGTH);
120 | } else {
121 | return readBits(QMC5883_ADDRESS, QMC5883_REG_CONFIG_1, QMC5883_CRA_AVERAGE_BIT, QMC5883_CRA_AVERAGE_LENGTH);
122 | }
123 | }
124 | /** Set number of samples averaged per measurement.
125 | * @param averaging New samples averaged per measurement setting(0-3 for 1/2/4/8 respectively)
126 | */
127 | void Mag5883::setSampleAveraging(uint8_t averaging) {
128 | if(isHMC_){
129 | writeBits(HMC5883L_ADDRESS, HMC5883L_REG_CONFIG_A, HMC5883L_CRA_AVERAGE_BIT, HMC5883L_CRA_AVERAGE_LENGTH, averaging);
130 | } else {
131 | writeBits(QMC5883_ADDRESS, QMC5883_REG_CONFIG_1, QMC5883_CRA_AVERAGE_BIT, QMC5883_CRA_AVERAGE_LENGTH, averaging);
132 | }
133 | }
134 |
135 | /** get magnetic field gain value
136 | ***** FOR HMC5883L *******
137 | * The table below shows nominal gain settings. Use the "Gain" column to convert
138 | * counts to Gauss. Choose a lower gain value (higher GN#) when total field
139 | * strength causes overflow in one of the data output registers (saturation).
140 | * The data output range for all settings is 0xF800-0x07FF (-2048 - 2047).
141 | *
142 | * Value | Field Range | Gain (LSB/Gauss)
143 | * ------+-------------+-----------------
144 | * 0 | +/- 0.88 Ga | 1370
145 | * 1 | +/- 1.3 Ga | 1090 (Default)
146 | * 2 | +/- 1.9 Ga | 820
147 | * 3 | +/- 2.5 Ga | 660
148 | * 4 | +/- 4.0 Ga | 440
149 | * 5 | +/- 4.7 Ga | 390
150 | * 6 | +/- 5.6 Ga | 330
151 | * 7 | +/- 8.1 Ga | 230
152 | *
153 | ***** FOR QMC5883 *******
154 | *
155 | * Value | Recommended Range
156 | * ------+------------
157 | * 0 | +/- 2 G
158 | * 1 | +/- 8 G
159 | *
160 | * @return Current magnetic field gain value
161 | */
162 | uint8_t Mag5883::getRange() {
163 | if(isHMC_){
164 | return readBits(HMC5883L_ADDRESS, HMC5883L_REG_CONFIG_B, HMC5883L_CRB_RANGE_BIT, HMC5883L_CRB_RANGE_LENGTH);
165 | } else {
166 | return readBits(QMC5883_ADDRESS, QMC5883_REG_CONFIG_1, QMC5883_CRB_RANGE_BIT, QMC5883_CRB_RANGE_LENGTH);
167 | }
168 | }
169 |
170 | /** Set magnetic field gain value
171 | */
172 | void Mag5883::setRange(uint8_t gain) {
173 | if(isHMC_){
174 | // use this method to guarantee that bits 4-0 are set to zero, which is a
175 | // requirement specified in the datasheet; it's actually more efficient than
176 | // using the I2Cdev.writeBits method
177 | writeByte(HMC5883L_ADDRESS, HMC5883L_REG_CONFIG_B, gain << 5);
178 | } else {
179 | writeBits(QMC5883_ADDRESS, QMC5883_REG_CONFIG_1, QMC5883_CRB_RANGE_BIT, QMC5883_CRB_RANGE_LENGTH, gain);
180 | }
181 | }
182 |
183 | /** Get measurement mode.
184 | ***** FOR HMC5883L *******
185 | * In continuous-measurement mode, the device continuously performs measurements
186 | * and places the result in the data register. RDY goes high when new data is
187 | * placed in all three registers. After a power-on or a write to the mode or
188 | * configuration register, the first measurement set is available from all three
189 | * data output registers after a period of 2/fDO and subsequent measurements are
190 | * available at a frequency of fDO, where fDO is the frequency of data output.
191 | *
192 | * When single-measurement mode (default) is selected, device performs a single
193 | * measurement, sets RDY high and returned to idle mode. Mode register returns
194 | * to idle mode bit values. The measurement remains in the data output register
195 | * and RDY remains high until the data output register is read or another
196 | * measurement is performed.
197 | *
198 | ***** FOR QMC5883 *******
199 | * Measurement mode is forced to continous, rate is defined by user
200 | */
201 |
202 | uint8_t Mag5883::getMode() {
203 | if(isHMC_){
204 | return readBits(HMC5883L_ADDRESS, HMC5883L_REG_MODE, HMC5883L_MODEREG_BIT, HMC5883L_MODEREG_LENGTH);
205 | } else {
206 | return 1; //measurement mode forced to continuous
207 | }
208 | }
209 |
210 | /** Set measurement mode (forced to continous for QMC5883)
211 | */
212 | void Mag5883::setMode(uint8_t newMode) {
213 | if(isHMC_){
214 | // use this method to guarantee that bits 7-2 are set to zero, which is a
215 | // requirement specified in the datasheet; it's actually more efficient than
216 | // using the I2Cdev.writeBits method
217 | writeByte(HMC5883L_ADDRESS, HMC5883L_REG_MODE, newMode << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1));
218 | mode = newMode; // track to tell if we have to clear bit 7 after a read
219 | } else {
220 | newMode = 1;// force to 1 (continuous)
221 | mode = newMode;
222 |
223 | writeBits(QMC5883_ADDRESS, QMC5883_REG_CONFIG_1, QMC5883_MODEREG_BIT, QMC5883_MODEREG_LENGTH, newMode);
224 | }
225 | }
226 |
227 | /** Get data output rate value.
228 | ***** FOR HMC5883L *******
229 | * The Table below shows all selectable output rates in continuous measurement
230 | * mode. All three channels shall be measured within a given output rate. Other
231 | * output rates with maximum rate of 160 Hz can be achieved by monitoring DRDY
232 | * interrupt pin in single measurement mode.
233 | *
234 | * Value | Typical Data Output Rate (Hz)
235 | * ------+------------------------------
236 | * 0 | 0.75
237 | * 1 | 1.5
238 | * 2 | 3
239 | * 3 | 7.5
240 | * 4 | 15 (Default)
241 | * 5 | 30
242 | * 6 | 75
243 | * 7 | Not used
244 | *
245 | *
246 | ***** FOR QMC5883 *******
247 | *
248 | * * Value | Typical Data Output Rate (Hz)
249 | * ------+------------------------------
250 | * 0 | 10
251 | * 1 | 50
252 | * 2 | 100
253 | * 3 | 200
254 | *
255 | * @return Current rate of data output to registers
256 | */
257 | uint8_t Mag5883::getDataRate() {
258 | return 1;
259 | if(isHMC_){
260 | return readBits(HMC5883L_ADDRESS, HMC5883L_REG_CONFIG_A, HMC5883L_CRA_RATE_BIT, HMC5883L_CRA_RATE_LENGTH);
261 | } else {
262 | return readBits(QMC5883_ADDRESS, QMC5883_REG_CONFIG_1, QMC5883_CRA_RATE_BIT, QMC5883_CRA_RATE_LENGTH);
263 | }
264 | }
265 |
266 | /** Set data output rate value.
267 | */
268 | void Mag5883::setDataRate(uint8_t rate) {
269 | if(isHMC_){
270 | writeBits(HMC5883L_ADDRESS, HMC5883L_REG_CONFIG_A, HMC5883L_CRA_RATE_BIT, HMC5883L_CRA_RATE_LENGTH, rate);
271 | } else {
272 | writeBits(QMC5883_ADDRESS, QMC5883_REG_CONFIG_1, QMC5883_CRA_RATE_BIT, QMC5883_CRA_RATE_LENGTH, rate);
273 | }
274 | }
275 |
276 |
277 | /** Get 3-axis heading measurements.
278 | * In the event the ADC reading overflows or underflows for the given channel,
279 | * or if there is a math overflow during the bias measurement, this data
280 | * register will contain the value -4096. This register value will clear when
281 | * after the next valid measurement is made. Note that this method automatically
282 | * clears the appropriate bit in the MODE register if Single mode is active.
283 | * @param x 16-bit signed integer container for X-axis heading
284 | * @param y 16-bit signed integer container for Y-axis heading
285 | * @param z 16-bit signed integer container for Z-axis heading
286 | * @see HMC5883L_RA_DATAX_H
287 | */
288 | void Mag5883::getHeading(int16_t *x, int16_t *y, int16_t *z) {
289 | if(isHMC_){
290 | readBytes(HMC5883L_ADDRESS, HMC5883L_REG_OUT_X_M, 6, buffer);
291 | if (mode == HMC5883L_MODE_SINGLE) writeByte(HMC5883L_ADDRESS, HMC5883L_REG_MODE, HMC5883L_MODE_SINGLE << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1));
292 | *x = (((int16_t)buffer[0]) << 8) | buffer[1];
293 | *y = (((int16_t)buffer[4]) << 8) | buffer[5];
294 | *z = (((int16_t)buffer[2]) << 8) | buffer[3];
295 | } else {
296 | readBytes(QMC5883_ADDRESS, QMC5883_REG_OUT_X_L, 6, buffer);
297 | //if (mode == HMC5883L_MODE_SINGLE) writeByte(devAddr, HMC5883L_RA_MODE, HMC5883L_MODE_SINGLE << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1));
298 | *x = (((int16_t)buffer[1]) << 8) | buffer[0]; // careful LSB before MSB
299 | *z = (((int16_t)buffer[5]) << 8) | buffer[4]; // careful LSB before MSB
300 | *y = (((int16_t)buffer[3]) << 8) | buffer[2]; // careful LSB before MSB
301 | }
302 | }
303 |
304 |
305 |
--------------------------------------------------------------------------------
/firmware/hedrot-firmware/ADXL345.h:
--------------------------------------------------------------------------------
1 | // ADXL345.cpp: ADXL345 I2C device methods
2 | // based on I2Cdev library collection - ADXL345 I2C device class
3 | // adapted for i2c_t3 through the custom code I2Ccom.cpp
4 |
5 | #ifndef _ADXL345_H_
6 | #define _ADXL345_H_
7 |
8 | #include "I2Ccom.h"
9 |
10 | #define ADXL345_ADDRESS_ALT_LOW 0x53 // alt address pin low (GND)
11 | #define ADXL345_ADDRESS_ALT_HIGH 0x1D // alt address pin high (VCC)
12 | #define ADXL345_DEFAULT_ADDRESS ADXL345_ADDRESS_ALT_LOW
13 |
14 | #define ADXL345_RA_DEVID 0x00
15 | #define ADXL345_RA_RESERVED1 0x01
16 | #define ADXL345_RA_THRESH_TAP 0x1D
17 | #define ADXL345_RA_OFSX 0x1E
18 | #define ADXL345_RA_OFSY 0x1F
19 | #define ADXL345_RA_OFSZ 0x20
20 | #define ADXL345_RA_DUR 0x21
21 | #define ADXL345_RA_LATENT 0x22
22 | #define ADXL345_RA_WINDOW 0x23
23 | #define ADXL345_RA_THRESH_ACT 0x24
24 | #define ADXL345_RA_THRESH_INACT 0x25
25 | #define ADXL345_RA_TIME_INACT 0x26
26 | #define ADXL345_RA_ACT_INACT_CTL 0x27
27 | #define ADXL345_RA_THRESH_FF 0x28
28 | #define ADXL345_RA_TIME_FF 0x29
29 | #define ADXL345_RA_TAP_AXES 0x2A
30 | #define ADXL345_RA_ACT_TAP_STATUS 0x2B
31 | #define ADXL345_RA_BW_RATE 0x2C
32 | #define ADXL345_RA_POWER_CTL 0x2D
33 | #define ADXL345_RA_INT_ENABLE 0x2E
34 | #define ADXL345_RA_INT_MAP 0x2F
35 | #define ADXL345_RA_INT_SOURCE 0x30
36 | #define ADXL345_RA_DATA_FORMAT 0x31
37 | #define ADXL345_RA_DATAX0 0x32
38 | #define ADXL345_RA_DATAX1 0x33
39 | #define ADXL345_RA_DATAY0 0x34
40 | #define ADXL345_RA_DATAY1 0x35
41 | #define ADXL345_RA_DATAZ0 0x36
42 | #define ADXL345_RA_DATAZ1 0x37
43 | #define ADXL345_RA_FIFO_CTL 0x38
44 | #define ADXL345_RA_FIFO_STATUS 0x39
45 |
46 | #define ADXL345_AIC_ACT_AC_BIT 7
47 | #define ADXL345_AIC_ACT_X_BIT 6
48 | #define ADXL345_AIC_ACT_Y_BIT 5
49 | #define ADXL345_AIC_ACT_Z_BIT 4
50 | #define ADXL345_AIC_INACT_AC_BIT 3
51 | #define ADXL345_AIC_INACT_X_BIT 2
52 | #define ADXL345_AIC_INACT_Y_BIT 1
53 | #define ADXL345_AIC_INACT_Z_BIT 0
54 |
55 | #define ADXL345_TAPAXIS_SUP_BIT 3
56 | #define ADXL345_TAPAXIS_X_BIT 2
57 | #define ADXL345_TAPAXIS_Y_BIT 1
58 | #define ADXL345_TAPAXIS_Z_BIT 0
59 |
60 | #define ADXL345_TAPSTAT_ACTX_BIT 6
61 | #define ADXL345_TAPSTAT_ACTY_BIT 5
62 | #define ADXL345_TAPSTAT_ACTZ_BIT 4
63 | #define ADXL345_TAPSTAT_ASLEEP_BIT 3
64 | #define ADXL345_TAPSTAT_TAPX_BIT 2
65 | #define ADXL345_TAPSTAT_TAPY_BIT 1
66 | #define ADXL345_TAPSTAT_TAPZ_BIT 0
67 |
68 | #define ADXL345_BW_LOWPOWER_BIT 4
69 | #define ADXL345_BW_RATE_BIT 3
70 | #define ADXL345_BW_RATE_LENGTH 4
71 |
72 | #define ADXL345_RATE_3200 0b1111
73 | #define ADXL345_RATE_1600 0b1110
74 | #define ADXL345_RATE_800 0b1101
75 | #define ADXL345_RATE_400 0b1100
76 | #define ADXL345_RATE_200 0b1011
77 | #define ADXL345_RATE_100 0b1010
78 | #define ADXL345_RATE_50 0b1001
79 | #define ADXL345_RATE_25 0b1000
80 | #define ADXL345_RATE_12P5 0b0111
81 | #define ADXL345_RATE_6P25 0b0110
82 | #define ADXL345_RATE_3P13 0b0101
83 | #define ADXL345_RATE_1P56 0b0100
84 | #define ADXL345_RATE_0P78 0b0011
85 | #define ADXL345_RATE_0P39 0b0010
86 | #define ADXL345_RATE_0P20 0b0001
87 | #define ADXL345_RATE_0P10 0b0000
88 |
89 | #define ADXL345_PCTL_LINK_BIT 5
90 | #define ADXL345_PCTL_AUTOSLEEP_BIT 4
91 | #define ADXL345_PCTL_MEASURE_BIT 3
92 | #define ADXL345_PCTL_SLEEP_BIT 2
93 | #define ADXL345_PCTL_WAKEUP_BIT 1
94 | #define ADXL345_PCTL_WAKEUP_LENGTH 2
95 |
96 | #define ADXL345_WAKEUP_8HZ 0b00
97 | #define ADXL345_WAKEUP_4HZ 0b01
98 | #define ADXL345_WAKEUP_2HZ 0b10
99 | #define ADXL345_WAKEUP_1HZ 0b11
100 |
101 | #define ADXL345_INT_DATA_READY_BIT 7
102 | #define ADXL345_INT_SINGLE_TAP_BIT 6
103 | #define ADXL345_INT_DOUBLE_TAP_BIT 5
104 | #define ADXL345_INT_ACTIVITY_BIT 4
105 | #define ADXL345_INT_INACTIVITY_BIT 3
106 | #define ADXL345_INT_FREE_FALL_BIT 2
107 | #define ADXL345_INT_WATERMARK_BIT 1
108 | #define ADXL345_INT_OVERRUN_BIT 0
109 |
110 | #define ADXL345_FORMAT_SELFTEST_BIT 7
111 | #define ADXL345_FORMAT_SPIMODE_BIT 6
112 | #define ADXL345_FORMAT_INTMODE_BIT 5
113 | #define ADXL345_FORMAT_FULL_RES_BIT 3
114 | #define ADXL345_FORMAT_JUSTIFY_BIT 2
115 | #define ADXL345_FORMAT_RANGE_BIT 1
116 | #define ADXL345_FORMAT_RANGE_LENGTH 2
117 |
118 | #define ADXL345_RANGE_2G 0b00
119 | #define ADXL345_RANGE_4G 0b01
120 | #define ADXL345_RANGE_8G 0b10
121 | #define ADXL345_RANGE_16G 0b11
122 |
123 | #define ADXL345_FIFO_MODE_BIT 7
124 | #define ADXL345_FIFO_MODE_LENGTH 2
125 | #define ADXL345_FIFO_TRIGGER_BIT 5
126 | #define ADXL345_FIFO_SAMPLES_BIT 4
127 | #define ADXL345_FIFO_SAMPLES_LENGTH 5
128 |
129 | #define ADXL345_FIFO_MODE_BYPASS 0b00
130 | #define ADXL345_FIFO_MODE_FIFO 0b01
131 | #define ADXL345_FIFO_MODE_STREAM 0b10
132 | #define ADXL345_FIFO_MODE_TRIGGER 0b11
133 |
134 | #define ADXL345_FIFOSTAT_TRIGGER_BIT 7
135 | #define ADXL345_FIFOSTAT_LENGTH_BIT 5
136 | #define ADXL345_FIFOSTAT_LENGTH_LENGTH 6
137 |
138 | class ADXL345 {
139 | public:
140 | ADXL345();
141 | ADXL345(uint8_t address);
142 |
143 | void initialize();
144 | bool testConnection();
145 |
146 | // DEVID register
147 | uint8_t getDeviceID();
148 |
149 | // THRESH_TAP register
150 | uint8_t getTapThreshold();
151 | void setTapThreshold(uint8_t threshold);
152 |
153 | // OFS* registers
154 | void getOffset(int8_t* x, int8_t* y, int8_t* z);
155 | void setOffset(int8_t x, int8_t y, int8_t z);
156 | int8_t getOffsetX();
157 | void setOffsetX(int8_t x);
158 | int8_t getOffsetY();
159 | void setOffsetY(int8_t y);
160 | int8_t getOffsetZ();
161 | void setOffsetZ(int8_t z);
162 |
163 | // DUR register
164 | uint8_t getTapDuration();
165 | void setTapDuration(uint8_t duration);
166 |
167 | // LATENT register
168 | uint8_t getDoubleTapLatency();
169 | void setDoubleTapLatency(uint8_t latency);
170 |
171 | // WINDOW register
172 | uint8_t getDoubleTapWindow();
173 | void setDoubleTapWindow(uint8_t window);
174 |
175 | // THRESH_ACT register
176 | uint8_t getActivityThreshold();
177 | void setActivityThreshold(uint8_t threshold);
178 |
179 | // THRESH_INACT register
180 | uint8_t getInactivityThreshold();
181 | void setInactivityThreshold(uint8_t threshold);
182 |
183 | // TIME_INACT register
184 | uint8_t getInactivityTime();
185 | void setInactivityTime(uint8_t time);
186 |
187 | // ACT_INACT_CTL register
188 | bool getActivityAC();
189 | void setActivityAC(bool enabled);
190 | bool getActivityXEnabled();
191 | void setActivityXEnabled(bool enabled);
192 | bool getActivityYEnabled();
193 | void setActivityYEnabled(bool enabled);
194 | bool getActivityZEnabled();
195 | void setActivityZEnabled(bool enabled);
196 | bool getInactivityAC();
197 | void setInactivityAC(bool enabled);
198 | bool getInactivityXEnabled();
199 | void setInactivityXEnabled(bool enabled);
200 | bool getInactivityYEnabled();
201 | void setInactivityYEnabled(bool enabled);
202 | bool getInactivityZEnabled();
203 | void setInactivityZEnabled(bool enabled);
204 |
205 | // THRESH_FF register
206 | uint8_t getFreefallThreshold();
207 | void setFreefallThreshold(uint8_t threshold);
208 |
209 | // TIME_FF register
210 | uint8_t getFreefallTime();
211 | void setFreefallTime(uint8_t time);
212 |
213 | // TAP_AXES register
214 | bool getTapAxisSuppress();
215 | void setTapAxisSuppress(bool enabled);
216 | bool getTapAxisXEnabled();
217 | void setTapAxisXEnabled(bool enabled);
218 | bool getTapAxisYEnabled();
219 | void setTapAxisYEnabled(bool enabled);
220 | bool getTapAxisZEnabled();
221 | void setTapAxisZEnabled(bool enabled);
222 |
223 | // ACT_TAP_STATUS register
224 | bool getActivitySourceX();
225 | bool getActivitySourceY();
226 | bool getActivitySourceZ();
227 | bool getAsleep();
228 | bool getTapSourceX();
229 | bool getTapSourceY();
230 | bool getTapSourceZ();
231 |
232 | // BW_RATE register
233 | bool getLowPowerEnabled();
234 | void setLowPowerEnabled(bool enabled);
235 | uint8_t getRate();
236 | void setRate(uint8_t rate);
237 |
238 | // POWER_CTL register
239 | bool getLinkEnabled();
240 | void setLinkEnabled(bool enabled);
241 | bool getAutoSleepEnabled();
242 | void setAutoSleepEnabled(bool enabled);
243 | bool getMeasureEnabled();
244 | void setMeasureEnabled(bool enabled);
245 | bool getSleepEnabled();
246 | void setSleepEnabled(bool enabled);
247 | uint8_t getWakeupFrequency();
248 | void setWakeupFrequency(uint8_t frequency);
249 |
250 | // INT_ENABLE register
251 | bool getIntDataReadyEnabled();
252 | void setIntDataReadyEnabled(bool enabled);
253 | bool getIntSingleTapEnabled();
254 | void setIntSingleTapEnabled(bool enabled);
255 | bool getIntDoubleTapEnabled();
256 | void setIntDoubleTapEnabled(bool enabled);
257 | bool getIntActivityEnabled();
258 | void setIntActivityEnabled(bool enabled);
259 | bool getIntInactivityEnabled();
260 | void setIntInactivityEnabled(bool enabled);
261 | bool getIntFreefallEnabled();
262 | void setIntFreefallEnabled(bool enabled);
263 | bool getIntWatermarkEnabled();
264 | void setIntWatermarkEnabled(bool enabled);
265 | bool getIntOverrunEnabled();
266 | void setIntOverrunEnabled(bool enabled);
267 |
268 | // INT_MAP register
269 | uint8_t getIntDataReadyPin();
270 | void setIntDataReadyPin(uint8_t pin);
271 | uint8_t getIntSingleTapPin();
272 | void setIntSingleTapPin(uint8_t pin);
273 | uint8_t getIntDoubleTapPin();
274 | void setIntDoubleTapPin(uint8_t pin);
275 | uint8_t getIntActivityPin();
276 | void setIntActivityPin(uint8_t pin);
277 | uint8_t getIntInactivityPin();
278 | void setIntInactivityPin(uint8_t pin);
279 | uint8_t getIntFreefallPin();
280 | void setIntFreefallPin(uint8_t pin);
281 | uint8_t getIntWatermarkPin();
282 | void setIntWatermarkPin(uint8_t pin);
283 | uint8_t getIntOverrunPin();
284 | void setIntOverrunPin(uint8_t pin);
285 |
286 | // INT_SOURCE register
287 | uint8_t getIntDataReadySource();
288 | uint8_t getIntSingleTapSource();
289 | uint8_t getIntDoubleTapSource();
290 | uint8_t getIntActivitySource();
291 | uint8_t getIntInactivitySource();
292 | uint8_t getIntFreefallSource();
293 | uint8_t getIntWatermarkSource();
294 | uint8_t getIntOverrunSource();
295 |
296 | // DATA_FORMAT register
297 | uint8_t getSelfTestEnabled();
298 | void setSelfTestEnabled(uint8_t enabled);
299 | uint8_t getSPIMode();
300 | void setSPIMode(uint8_t mode);
301 | uint8_t getInterruptMode();
302 | void setInterruptMode(uint8_t mode);
303 | uint8_t getFullResolution();
304 | void setFullResolution(uint8_t resolution);
305 | uint8_t getDataJustification();
306 | void setDataJustification(uint8_t justification);
307 | uint8_t getRange();
308 | void setRange(uint8_t range);
309 |
310 | // DATA* registers
311 | void getAcceleration(int16_t* x, int16_t* y, int16_t* z);
312 | int16_t getAccelerationX();
313 | int16_t getAccelerationY();
314 | int16_t getAccelerationZ();
315 |
316 | // FIFO_CTL register
317 | uint8_t getFIFOMode();
318 | void setFIFOMode(uint8_t mode);
319 | uint8_t getFIFOTriggerInterruptPin();
320 | void setFIFOTriggerInterruptPin(uint8_t interrupt);
321 | uint8_t getFIFOSamples();
322 | void setFIFOSamples(uint8_t size);
323 |
324 | // FIFO_STATUS register
325 | bool getFIFOTriggerOccurred();
326 | uint8_t getFIFOLength();
327 |
328 | private:
329 | uint8_t devAddr;
330 | uint8_t buffer[6];
331 | };
332 |
333 | #endif /* _ADXL345_H_ */
334 |
--------------------------------------------------------------------------------
/command-line-demo/xcode/hedrotReceiverDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 164863FC1F27940E00698E6C /* libhedrot_calibration.c in Sources */ = {isa = PBXBuildFile; fileRef = 164863F61F27940E00698E6C /* libhedrot_calibration.c */; };
11 | 164863FD1F27940E00698E6C /* libhedrot_RTmagCalibration.c in Sources */ = {isa = PBXBuildFile; fileRef = 164863F81F27940E00698E6C /* libhedrot_RTmagCalibration.c */; };
12 | 164863FE1F27940E00698E6C /* libhedrot_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 164863FA1F27940E00698E6C /* libhedrot_utils.c */; };
13 | 16FEAF4E1DCBDB1B007B9E47 /* hedrotReceiverDemo.c in Sources */ = {isa = PBXBuildFile; fileRef = 16FEAF4D1DCBDB1B007B9E47 /* hedrotReceiverDemo.c */; };
14 | 16FEAF5A1DCBDB51007B9E47 /* libhedrot.c in Sources */ = {isa = PBXBuildFile; fileRef = 16FEAF561DCBDB4A007B9E47 /* libhedrot.c */; };
15 | 16FEAF5B1DCBDB53007B9E47 /* libhedrot_serialcomm.c in Sources */ = {isa = PBXBuildFile; fileRef = 16FEAF581DCBDB4A007B9E47 /* libhedrot_serialcomm.c */; };
16 | /* End PBXBuildFile section */
17 |
18 | /* Begin PBXFileReference section */
19 | 164863F61F27940E00698E6C /* libhedrot_calibration.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libhedrot_calibration.c; sourceTree = ""; };
20 | 164863F71F27940E00698E6C /* libhedrot_calibration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libhedrot_calibration.h; sourceTree = ""; };
21 | 164863F81F27940E00698E6C /* libhedrot_RTmagCalibration.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libhedrot_RTmagCalibration.c; sourceTree = ""; };
22 | 164863F91F27940E00698E6C /* libhedrot_RTmagCalibration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libhedrot_RTmagCalibration.h; sourceTree = ""; };
23 | 164863FA1F27940E00698E6C /* libhedrot_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libhedrot_utils.c; sourceTree = ""; };
24 | 164863FB1F27940E00698E6C /* libhedrot_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libhedrot_utils.h; sourceTree = ""; };
25 | 166D0E481DB3E54D007B85B9 /* hedrotReceiverDemo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = hedrotReceiverDemo; sourceTree = BUILT_PRODUCTS_DIR; };
26 | 16FEAF4D1DCBDB1B007B9E47 /* hedrotReceiverDemo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hedrotReceiverDemo.c; path = ../source/hedrotReceiverDemo.c; sourceTree = ""; };
27 | 16FEAF561DCBDB4A007B9E47 /* libhedrot.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = libhedrot.c; sourceTree = ""; };
28 | 16FEAF571DCBDB4A007B9E47 /* libhedrot.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libhedrot.h; sourceTree = ""; };
29 | 16FEAF581DCBDB4A007B9E47 /* libhedrot_serialcomm.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = libhedrot_serialcomm.c; sourceTree = ""; };
30 | 16FEAF591DCBDB4A007B9E47 /* libhedrot_serialcomm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libhedrot_serialcomm.h; sourceTree = ""; };
31 | 16FEAF5C1DCBDB6A007B9E47 /* hedrot_comm_protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = hedrot_comm_protocol.h; sourceTree = ""; };
32 | /* End PBXFileReference section */
33 |
34 | /* Begin PBXFrameworksBuildPhase section */
35 | 166D0E451DB3E54D007B85B9 /* Frameworks */ = {
36 | isa = PBXFrameworksBuildPhase;
37 | buildActionMask = 2147483647;
38 | files = (
39 | );
40 | runOnlyForDeploymentPostprocessing = 0;
41 | };
42 | /* End PBXFrameworksBuildPhase section */
43 |
44 | /* Begin PBXGroup section */
45 | 166D0E3F1DB3E54D007B85B9 = {
46 | isa = PBXGroup;
47 | children = (
48 | 16FEAF5D1DCBDB6E007B9E47 /* firmware */,
49 | 16FEAF4D1DCBDB1B007B9E47 /* hedrotReceiverDemo.c */,
50 | 16FEAF551DCBDB4A007B9E47 /* libhedrot */,
51 | 166D0E491DB3E54D007B85B9 /* Products */,
52 | );
53 | sourceTree = "";
54 | };
55 | 166D0E491DB3E54D007B85B9 /* Products */ = {
56 | isa = PBXGroup;
57 | children = (
58 | 166D0E481DB3E54D007B85B9 /* hedrotReceiverDemo */,
59 | );
60 | name = Products;
61 | sourceTree = "";
62 | };
63 | 16FEAF551DCBDB4A007B9E47 /* libhedrot */ = {
64 | isa = PBXGroup;
65 | children = (
66 | 16FEAF561DCBDB4A007B9E47 /* libhedrot.c */,
67 | 16FEAF571DCBDB4A007B9E47 /* libhedrot.h */,
68 | 16FEAF581DCBDB4A007B9E47 /* libhedrot_serialcomm.c */,
69 | 16FEAF591DCBDB4A007B9E47 /* libhedrot_serialcomm.h */,
70 | 164863F61F27940E00698E6C /* libhedrot_calibration.c */,
71 | 164863F71F27940E00698E6C /* libhedrot_calibration.h */,
72 | 164863F81F27940E00698E6C /* libhedrot_RTmagCalibration.c */,
73 | 164863F91F27940E00698E6C /* libhedrot_RTmagCalibration.h */,
74 | 164863FA1F27940E00698E6C /* libhedrot_utils.c */,
75 | 164863FB1F27940E00698E6C /* libhedrot_utils.h */,
76 | );
77 | name = libhedrot;
78 | path = ../../libhedrot;
79 | sourceTree = "";
80 | };
81 | 16FEAF5D1DCBDB6E007B9E47 /* firmware */ = {
82 | isa = PBXGroup;
83 | children = (
84 | 16FEAF5C1DCBDB6A007B9E47 /* hedrot_comm_protocol.h */,
85 | );
86 | name = firmware;
87 | path = "../../firmware/hedrot-firmware";
88 | sourceTree = SOURCE_ROOT;
89 | };
90 | /* End PBXGroup section */
91 |
92 | /* Begin PBXNativeTarget section */
93 | 166D0E471DB3E54D007B85B9 /* hedrotReceiverDemo */ = {
94 | isa = PBXNativeTarget;
95 | buildConfigurationList = 166D0E4F1DB3E54D007B85B9 /* Build configuration list for PBXNativeTarget "hedrotReceiverDemo" */;
96 | buildPhases = (
97 | 166D0E441DB3E54D007B85B9 /* Sources */,
98 | 166D0E451DB3E54D007B85B9 /* Frameworks */,
99 | 16728FBB1DCBDD4500F780CB /* ShellScript */,
100 | );
101 | buildRules = (
102 | );
103 | dependencies = (
104 | );
105 | name = hedrotReceiverDemo;
106 | productName = headtracker_rcv_cmd;
107 | productReference = 166D0E481DB3E54D007B85B9 /* hedrotReceiverDemo */;
108 | productType = "com.apple.product-type.tool";
109 | };
110 | /* End PBXNativeTarget section */
111 |
112 | /* Begin PBXProject section */
113 | 166D0E401DB3E54D007B85B9 /* Project object */ = {
114 | isa = PBXProject;
115 | attributes = {
116 | LastUpgradeCheck = 0820;
117 | ORGANIZATIONNAME = "Alexis Baskind";
118 | TargetAttributes = {
119 | 166D0E471DB3E54D007B85B9 = {
120 | CreatedOnToolsVersion = 6.2;
121 | };
122 | };
123 | };
124 | buildConfigurationList = 166D0E431DB3E54D007B85B9 /* Build configuration list for PBXProject "hedrotReceiverDemo" */;
125 | compatibilityVersion = "Xcode 3.2";
126 | developmentRegion = English;
127 | hasScannedForEncodings = 0;
128 | knownRegions = (
129 | en,
130 | );
131 | mainGroup = 166D0E3F1DB3E54D007B85B9;
132 | productRefGroup = 166D0E491DB3E54D007B85B9 /* Products */;
133 | projectDirPath = "";
134 | projectRoot = "";
135 | targets = (
136 | 166D0E471DB3E54D007B85B9 /* hedrotReceiverDemo */,
137 | );
138 | };
139 | /* End PBXProject section */
140 |
141 | /* Begin PBXShellScriptBuildPhase section */
142 | 16728FBB1DCBDD4500F780CB /* ShellScript */ = {
143 | isa = PBXShellScriptBuildPhase;
144 | buildActionMask = 2147483647;
145 | files = (
146 | );
147 | inputPaths = (
148 | );
149 | outputPaths = (
150 | );
151 | runOnlyForDeploymentPostprocessing = 0;
152 | shellPath = /bin/sh;
153 | shellScript = "cp ${BUILT_PRODUCTS_DIR}/${EXECUTABLE_NAME} .";
154 | };
155 | /* End PBXShellScriptBuildPhase section */
156 |
157 | /* Begin PBXSourcesBuildPhase section */
158 | 166D0E441DB3E54D007B85B9 /* Sources */ = {
159 | isa = PBXSourcesBuildPhase;
160 | buildActionMask = 2147483647;
161 | files = (
162 | 164863FD1F27940E00698E6C /* libhedrot_RTmagCalibration.c in Sources */,
163 | 164863FC1F27940E00698E6C /* libhedrot_calibration.c in Sources */,
164 | 16FEAF4E1DCBDB1B007B9E47 /* hedrotReceiverDemo.c in Sources */,
165 | 164863FE1F27940E00698E6C /* libhedrot_utils.c in Sources */,
166 | 16FEAF5B1DCBDB53007B9E47 /* libhedrot_serialcomm.c in Sources */,
167 | 16FEAF5A1DCBDB51007B9E47 /* libhedrot.c in Sources */,
168 | );
169 | runOnlyForDeploymentPostprocessing = 0;
170 | };
171 | /* End PBXSourcesBuildPhase section */
172 |
173 | /* Begin XCBuildConfiguration section */
174 | 166D0E4D1DB3E54D007B85B9 /* Debug */ = {
175 | isa = XCBuildConfiguration;
176 | buildSettings = {
177 | ALWAYS_SEARCH_USER_PATHS = NO;
178 | ARCHS = "$(ARCHS_STANDARD)";
179 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
180 | CLANG_CXX_LIBRARY = "libc++";
181 | CLANG_ENABLE_MODULES = YES;
182 | CLANG_ENABLE_OBJC_ARC = YES;
183 | CLANG_WARN_BOOL_CONVERSION = YES;
184 | CLANG_WARN_CONSTANT_CONVERSION = YES;
185 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
186 | CLANG_WARN_EMPTY_BODY = YES;
187 | CLANG_WARN_ENUM_CONVERSION = YES;
188 | CLANG_WARN_INFINITE_RECURSION = YES;
189 | CLANG_WARN_INT_CONVERSION = YES;
190 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
191 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
192 | CLANG_WARN_UNREACHABLE_CODE = YES;
193 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
194 | COPY_PHASE_STRIP = NO;
195 | ENABLE_STRICT_OBJC_MSGSEND = YES;
196 | ENABLE_TESTABILITY = YES;
197 | GCC_C_LANGUAGE_STANDARD = gnu99;
198 | GCC_DYNAMIC_NO_PIC = NO;
199 | GCC_NO_COMMON_BLOCKS = YES;
200 | GCC_OPTIMIZATION_LEVEL = 0;
201 | GCC_PREPROCESSOR_DEFINITIONS = (
202 | "DEBUG=1",
203 | "$(inherited)",
204 | );
205 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
206 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
207 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
208 | GCC_WARN_UNDECLARED_SELECTOR = YES;
209 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
210 | GCC_WARN_UNUSED_FUNCTION = YES;
211 | GCC_WARN_UNUSED_VARIABLE = YES;
212 | MACOSX_DEPLOYMENT_TARGET = 10.9;
213 | MTL_ENABLE_DEBUG_INFO = YES;
214 | ONLY_ACTIVE_ARCH = YES;
215 | SDKROOT = macosx10.9;
216 | };
217 | name = Debug;
218 | };
219 | 166D0E4E1DB3E54D007B85B9 /* Release */ = {
220 | isa = XCBuildConfiguration;
221 | buildSettings = {
222 | ALWAYS_SEARCH_USER_PATHS = NO;
223 | ARCHS = "$(ARCHS_STANDARD)";
224 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
225 | CLANG_CXX_LIBRARY = "libc++";
226 | CLANG_ENABLE_MODULES = YES;
227 | CLANG_ENABLE_OBJC_ARC = YES;
228 | CLANG_WARN_BOOL_CONVERSION = YES;
229 | CLANG_WARN_CONSTANT_CONVERSION = YES;
230 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
231 | CLANG_WARN_EMPTY_BODY = YES;
232 | CLANG_WARN_ENUM_CONVERSION = YES;
233 | CLANG_WARN_INFINITE_RECURSION = YES;
234 | CLANG_WARN_INT_CONVERSION = YES;
235 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
236 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
237 | CLANG_WARN_UNREACHABLE_CODE = YES;
238 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
239 | COPY_PHASE_STRIP = NO;
240 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
241 | ENABLE_NS_ASSERTIONS = NO;
242 | ENABLE_STRICT_OBJC_MSGSEND = YES;
243 | GCC_C_LANGUAGE_STANDARD = gnu99;
244 | GCC_NO_COMMON_BLOCKS = YES;
245 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
246 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
247 | GCC_WARN_UNDECLARED_SELECTOR = YES;
248 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
249 | GCC_WARN_UNUSED_FUNCTION = YES;
250 | GCC_WARN_UNUSED_VARIABLE = YES;
251 | MACOSX_DEPLOYMENT_TARGET = 10.9;
252 | MTL_ENABLE_DEBUG_INFO = NO;
253 | SDKROOT = macosx10.9;
254 | };
255 | name = Release;
256 | };
257 | 166D0E501DB3E54D007B85B9 /* Debug */ = {
258 | isa = XCBuildConfiguration;
259 | buildSettings = {
260 | PRODUCT_NAME = hedrotReceiverDemo;
261 | SDKROOT = macosx10.9;
262 | };
263 | name = Debug;
264 | };
265 | 166D0E511DB3E54D007B85B9 /* Release */ = {
266 | isa = XCBuildConfiguration;
267 | buildSettings = {
268 | PRODUCT_NAME = hedrotReceiverDemo;
269 | SDKROOT = macosx10.9;
270 | };
271 | name = Release;
272 | };
273 | /* End XCBuildConfiguration section */
274 |
275 | /* Begin XCConfigurationList section */
276 | 166D0E431DB3E54D007B85B9 /* Build configuration list for PBXProject "hedrotReceiverDemo" */ = {
277 | isa = XCConfigurationList;
278 | buildConfigurations = (
279 | 166D0E4D1DB3E54D007B85B9 /* Debug */,
280 | 166D0E4E1DB3E54D007B85B9 /* Release */,
281 | );
282 | defaultConfigurationIsVisible = 0;
283 | defaultConfigurationName = Release;
284 | };
285 | 166D0E4F1DB3E54D007B85B9 /* Build configuration list for PBXNativeTarget "hedrotReceiverDemo" */ = {
286 | isa = XCConfigurationList;
287 | buildConfigurations = (
288 | 166D0E501DB3E54D007B85B9 /* Debug */,
289 | 166D0E511DB3E54D007B85B9 /* Release */,
290 | );
291 | defaultConfigurationIsVisible = 0;
292 | defaultConfigurationName = Release;
293 | };
294 | /* End XCConfigurationList section */
295 | };
296 | rootObject = 166D0E401DB3E54D007B85B9 /* Project object */;
297 | }
298 |
--------------------------------------------------------------------------------
/hedrotReceiver/source/hedrot_receiver.h:
--------------------------------------------------------------------------------
1 | // hedrot_receiver.h
2 | //
3 | // Copyright 2016 Alexis Baskind
4 |
5 | #ifndef hedrot_receiver_h
6 | #define hedrot_receiver_h
7 |
8 | #include "ext.h"
9 | #include "ext_common.h"
10 | #include "ext_strings.h"
11 | #include "ext_proto.h"
12 | #include "ext_support.h"
13 | #include "ext_maxtypes.h"
14 | #include "ext_mess.h"
15 | #include "ext_user.h"
16 | #include "ext_critical.h"
17 | #include "ext_dictobj.h"
18 | #include "jit.common.h"
19 | #include "z_dsp.h"
20 | #include "ext_buffer.h"
21 |
22 | #include
23 | #include
24 | #include
25 |
26 | #include "libhedrot.h"
27 | #include "hedrot_comm_protocol.h"
28 |
29 | // time constants
30 | #define SEARCHING_DEVICE_TIME 200 //time period between two ticks when the headtracker has still not been found
31 |
32 | typedef struct hedrot_receiver
33 | {
34 | t_object x_obj;
35 |
36 | //outlets
37 | void *x_rawData_outlet;
38 | void *x_calData_outlet;
39 | void *x_cookedAngles_outlet;
40 | void *x_cookedQuaternions_outlet;
41 | void *x_status_outlet;
42 | void *x_error_outlet;
43 | void *x_debug_outlet;
44 |
45 |
46 | // general variables about information reception
47 | t_object *receive_and_output_clock;
48 |
49 | headtrackerData *trackingData;
50 |
51 | // mirror of the internal settings of the structure trackingData that are used as attributes by Max
52 | // unfortunately necessary, since attributes can be only linked to variables on the top level of the Max object struct
53 | char verbose;
54 | char headtracker_on;
55 | char autoDiscover;
56 | char outputCenteredAngles;
57 | long samplerate;
58 | unsigned char gyroDataRate;
59 | unsigned char gyroClockSource;
60 | unsigned char gyroDLPFBandwidth;
61 | unsigned char gyroOffsetAutocalOn;
62 | unsigned char accRange;
63 | long accHardOffset[3]; // the Max API does not seem to handle signed char arrays => need to handle it as long
64 | unsigned char accFullResolutionBit;
65 | unsigned char accDataRate;
66 | unsigned char magMeasurementBias;
67 | unsigned char magSampleAveraging;
68 | unsigned char magDataRate;
69 | unsigned char magRange;
70 | unsigned char magMeasurementMode;
71 | float gyroOffsetAutocalTime; // in ms
72 | long gyroOffsetAutocalThreshold; //in LSB units
73 | float accOffset[3];
74 | float accScaling[3];
75 | float magOffset[3];
76 | float magScaling[3];
77 |
78 | char estimationMethod;
79 | float MadgwickBetaMax;
80 | float MadgwickBetaGain;
81 | float accLPtimeConstant;
82 | char axesReference;
83 | char rotationOrder;
84 | char invertRotation;
85 | float accCalMaxGyroNorm;
86 | char offlineCalibrationMethod; //0 = double ellipsoid fit, 1 = Aussal
87 | char RTmagCalibrationMethod; //0 = direct, 1 = iterative
88 | char RTmagCalOn;
89 | float RTmagMaxMemoryDuration; // RT mag calibration step 1: maximum duration of the memory used for calibration, in seconds
90 | float RTmagMaxDistanceError; // for RT mag calibration step 2, tolerance on the radius for new points
91 | float RTMagCalibrationPeriod; // RT mag calibration period in seconds
92 |
93 |
94 | // output data
95 | t_atom t_estimatedAngles[3];
96 | t_atom t_estimatedQuaternion[4];
97 |
98 | t_dictionary *magCalInfoDict;
99 | t_symbol *magCalInfoDictName;
100 | t_jit_object *magCalDataCalSamples_Matrix;
101 | t_buffer_obj *magCalDataCalNorm_BufferObj;
102 | t_symbol *magCalDataCalNorm_BufferObjName;
103 |
104 | t_dictionary *accCalInfoDict;
105 | t_symbol *accCalInfoDictName;
106 | t_jit_object *accCalDataCalSamples_Matrix;
107 | t_buffer_obj *accCalDataCalNorm_BufferObj;
108 | t_symbol *accCalDataCalNorm_BufferObjName;
109 |
110 | t_dictionary *RTmagCalInfoDict;
111 | t_symbol *RTmagCalInfoDictName;
112 | void *RTmagCalDataCalSamples_Matrix;
113 | t_buffer_obj *RTmagCalDataCalNorm_BufferObj;
114 | t_symbol *RTmagCalDataCalNorm_BufferObjName;
115 |
116 |
117 | // (control) output data rate
118 | long outputDataPeriod;
119 |
120 | // list to be send after formating...
121 | t_atom rawData[9];
122 | // ... and after calibration
123 | t_atom calData[9];
124 |
125 | // rec into text file
126 | char filename[MAX_PATH_CHARS];
127 | t_filehandle fh_write;
128 | char recordingDataFlag;
129 | long recsampleCount;
130 | char tmpStr[1024];
131 |
132 | } t_hedrot_receiver;
133 |
134 |
135 | t_class *hedrot_receiver_class;
136 |
137 |
138 | void *hedrot_receiver_new(t_symbol *s, short ac, t_atom *av);
139 | void hedrot_receiver_init(t_hedrot_receiver *x);
140 | void hedrot_receiver_tick(t_hedrot_receiver *x);
141 | void hedrot_receiver_free_clock(t_hedrot_receiver *x);
142 | void hedrot_receiver_free(t_hedrot_receiver *x);
143 |
144 | // methods
145 | void hedrot_receiver_open(t_hedrot_receiver *x, int n);
146 | void hedrot_receiver_close(t_hedrot_receiver *x);
147 | void hedrot_receiver_devices(t_hedrot_receiver *x);
148 | void hedrot_receiver_assist(t_hedrot_receiver *x, void *b, long m, long a, char *s);
149 | void hedrot_receiver_center_angles(t_hedrot_receiver *x);
150 |
151 | // methods for importing/exporting headtracker settings
152 | void hedrot_receiver_export_settings(t_hedrot_receiver *x, t_symbol *s);
153 | void hedrot_receiver_defered_export_settings(t_hedrot_receiver *x, t_symbol *s);
154 | void hedrot_receiver_import_settings(t_hedrot_receiver *x, t_symbol *s);
155 | void hedrot_receiver_defered_import_settings(t_hedrot_receiver *x, t_symbol *s);
156 | void hedrot_receiver_printVersion(t_hedrot_receiver *x, t_symbol *s);
157 |
158 | // methods for recording data into a text file
159 | void hedrot_receiver_opendestinationtextfile(t_hedrot_receiver *x, t_symbol *s);
160 | void hedrot_receiver_doopenforwrite(t_hedrot_receiver *x, t_symbol *s);
161 | void hedrot_receiver_startrec(t_hedrot_receiver *x);
162 | void hedrot_receiver_stoprec(t_hedrot_receiver *x);
163 |
164 | // generic methods for calibration
165 | char hedrot_receiver_createCalDataDictionary( float offset[], float scaling[], calibrationData *calData,
166 | t_dictionary *calDict, void *sampleMatrix,
167 | t_buffer_obj *normBufferObj, t_symbol *normBufferObjName);
168 |
169 | // methods for mag calibration
170 | void hedrot_receiver_startMagCalibration(t_hedrot_receiver *x);
171 | void hedrot_receiver_stopMagCalibration(t_hedrot_receiver *x);
172 | void hedrot_receiver_redoMagCalibration(t_hedrot_receiver *x);
173 | void hedrot_receiver_saveMagCalibration(t_hedrot_receiver *x);
174 | void hedrot_receiver_dumpMagCalInfo(t_hedrot_receiver *x);
175 | void hedrot_receiver_exportMagRawCalData(t_hedrot_receiver *x, t_symbol *s);
176 | void hedrot_receiver_defered_exportMagRawCalData(t_hedrot_receiver *x, t_symbol *s);
177 |
178 | // methods for acc calibration
179 | void hedrot_receiver_startAccCalibration(t_hedrot_receiver *x);
180 | void hedrot_receiver_stopAccCalibration(t_hedrot_receiver *x);
181 | void hedrot_receiver_redoAccCalibration(t_hedrot_receiver *x);
182 | void hedrot_receiver_saveAccCalibration(t_hedrot_receiver *x);
183 | void hedrot_receiver_dumpAccCalInfo(t_hedrot_receiver *x);
184 | void hedrot_receiver_exportAccRawCalData(t_hedrot_receiver *x, t_symbol *s);
185 | void hedrot_receiver_defered_exportAccRawCalData(t_hedrot_receiver *x, t_symbol *s);
186 |
187 | // methods for mag RT calibration
188 | void hedrot_receiver_dumpRTmagCalInfo(t_hedrot_receiver *x);
189 | void hedrot_receiver_exportRTmagRawCalData(t_hedrot_receiver *x, t_symbol *s);
190 | void hedrot_receiver_defered_exportRTmagRawCalData(t_hedrot_receiver *x, t_symbol *s);
191 |
192 | void hedrot_receiver_output_data(t_hedrot_receiver *x);
193 |
194 |
195 | void hedrot_receiver_autodiscover_deferedTick(t_hedrot_receiver *x, t_symbol *s, long argc, t_atom *argv);
196 |
197 |
198 | // output messages
199 | void hedrot_receiver_outputPortList(t_hedrot_receiver *x);
200 | void hedrot_receiver_selectOpenedPortInList(t_hedrot_receiver *x);
201 | void hedrot_receiver_outputWrongFirmwareVersionNotice(t_hedrot_receiver *x);
202 | void hedrot_receiver_outputReceptionStatus(t_hedrot_receiver *x);
203 | void hedrot_receiver_mirrorHeadtrackerInfo(t_hedrot_receiver *x);
204 | void hedrot_receiver_outputCalibrationNotValidNotice(t_hedrot_receiver *x);
205 | void hedrot_receiver_outputGyroCalibrationStartedNotice(t_hedrot_receiver *x);
206 | void hedrot_receiver_outputGyroCalibrationFinishedNotice(t_hedrot_receiver *x);
207 | void hedrot_receiver_outputMagCalibrationStartedNotice(t_hedrot_receiver *x);
208 | void hedrot_receiver_outputMagCalibrationSucceededNotice(t_hedrot_receiver *x);
209 | void hedrot_receiver_outputMagCalibrationFailedNotice(t_hedrot_receiver *x);
210 | void hedrot_receiver_outputAccCalibrationStartedNotice(t_hedrot_receiver *x);
211 | void hedrot_receiver_outputAccCalibrationSucceededNotice(t_hedrot_receiver *x);
212 | void hedrot_receiver_outputAccCalibrationFailedNotice(t_hedrot_receiver *x);
213 | void hedrot_receiver_outputAccCalibrationPausedNotice(t_hedrot_receiver *x);
214 | void hedrot_receiver_outputAccCalibrationResumedNotice(t_hedrot_receiver *x);
215 | void hedrot_receiver_boardOverloadNotice(t_hedrot_receiver *x);
216 |
217 |
218 | //getters and setters
219 | t_max_err hedrot_receiver_verbose_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
220 | t_max_err hedrot_receiver_headtracker_on_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
221 | t_max_err hedrot_receiver_autoDiscover_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
222 | t_max_err hedrot_receiver_samplerate_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
223 | t_max_err hedrot_receiver_outputCenteredAngles_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
224 | t_max_err hedrot_receiver_gyroDataRate_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
225 | t_max_err hedrot_receiver_gyroClockSource_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
226 | t_max_err hedrot_receiver_gyroDLPFBandwidth_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
227 | t_max_err hedrot_receiver_accRange_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
228 | t_max_err hedrot_receiver_accHardOffset_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
229 | t_max_err hedrot_receiver_accFullResolutionBit_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
230 | t_max_err hedrot_receiver_accDataRate_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
231 | t_max_err hedrot_receiver_magMeasurementBias_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
232 | t_max_err hedrot_receiver_magSampleAveraging_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
233 | t_max_err hedrot_receiver_magDataRate_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
234 | t_max_err hedrot_receiver_magRange_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv) ;
235 | t_max_err hedrot_receiver_magMeasurementMode_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
236 | t_max_err hedrot_receiver_gyroOffsetAutocalOn_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
237 | t_max_err hedrot_receiver_gyroOffsetAutocalTime_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
238 | t_max_err hedrot_receiver_gyroOffsetAutocalThreshold_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
239 | void hedrot_receiver_do_set_gyroOffsetAutocalOn(t_hedrot_receiver *x, char gyroOffsetAutocalOn);
240 | t_max_err hedrot_receiver_accOffset_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
241 | t_max_err hedrot_receiver_accScaling_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
242 | t_max_err hedrot_receiver_magOffset_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
243 | t_max_err hedrot_receiver_magScaling_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
244 | t_max_err hedrot_receiver_outputDataPeriod_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
245 |
246 |
247 | t_max_err hedrot_receiver_estimationMethod_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
248 | t_max_err hedrot_receiver_MadgwickBetaGain_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
249 | t_max_err hedrot_receiver_MadgwickBetaMax_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
250 | t_max_err hedrot_receiver_accLPtimeConstant_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
251 | t_max_err hedrot_receiver_axesReference_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
252 | t_max_err hedrot_receiver_rotationOrder_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
253 | t_max_err hedrot_receiver_invertRotation_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
254 | t_max_err hedrot_receiver_accCalMaxGyroNorm_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
255 | t_max_err hedrot_receiver_offlineCalibrationMethod_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
256 | t_max_err hedrot_receiver_RTmagCalibrationMethod_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
257 | t_max_err hedrot_receiver_RTmagCalOn_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
258 | t_max_err hedrot_receiver_RTmagMaxMemoryDuration_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
259 | t_max_err hedrot_receiver_RTmagMaxDistanceError_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
260 | t_max_err hedrot_receiver_RTMagCalibrationPeriod_set(t_hedrot_receiver *x, t_object *attr, long argc, t_atom *argv);
261 |
262 |
263 | #endif
264 |
--------------------------------------------------------------------------------
/hedrotReceiver/xcode/hedrot_receiver.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1629E7D31DCBBC70006ACD46 /* hedrot_comm_protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 1629E7D21DCBBC70006ACD46 /* hedrot_comm_protocol.h */; };
11 | 166427351E9F949D0081EE9E /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 166427341E9F949D0081EE9E /* Accelerate.framework */; };
12 | 167539AD1EA3A0F60062BDCE /* commonsyms.c in Sources */ = {isa = PBXBuildFile; fileRef = 167539AC1EA3A0F60062BDCE /* commonsyms.c */; };
13 | 16904B091EACA9F100517871 /* JitterAPI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 16904B081EACA9F100517871 /* JitterAPI.framework */; };
14 | 16904B0B1EACBE1D00517871 /* MaxAudioAPI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 16904B0A1EACBE1D00517871 /* MaxAudioAPI.framework */; };
15 | 1695F0051A87997F00708733 /* hedrot_receiver.c in Sources */ = {isa = PBXBuildFile; fileRef = 1695F0041A87997F00708733 /* hedrot_receiver.c */; };
16 | 16B2FC731DC9F69B003EECB3 /* libhedrot_serialcomm.c in Sources */ = {isa = PBXBuildFile; fileRef = 16B2FC6F1DC9F69B003EECB3 /* libhedrot_serialcomm.c */; };
17 | 16B2FC741DC9F69B003EECB3 /* libhedrot_serialcomm.h in Headers */ = {isa = PBXBuildFile; fileRef = 16B2FC701DC9F69B003EECB3 /* libhedrot_serialcomm.h */; };
18 | 16B2FC751DC9F69B003EECB3 /* libhedrot.c in Sources */ = {isa = PBXBuildFile; fileRef = 16B2FC711DC9F69B003EECB3 /* libhedrot.c */; };
19 | 16B2FC761DC9F69B003EECB3 /* libhedrot.h in Headers */ = {isa = PBXBuildFile; fileRef = 16B2FC721DC9F69B003EECB3 /* libhedrot.h */; };
20 | 16F0E6821EA4CAC500365603 /* libhedrot_calibration.c in Sources */ = {isa = PBXBuildFile; fileRef = 16F0E6801EA4CAC500365603 /* libhedrot_calibration.c */; };
21 | 16F0E6831EA4CAC500365603 /* libhedrot_calibration.h in Headers */ = {isa = PBXBuildFile; fileRef = 16F0E6811EA4CAC500365603 /* libhedrot_calibration.h */; };
22 | 16F0E6861EA4CB6F00365603 /* libhedrot_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 16F0E6841EA4CB6F00365603 /* libhedrot_utils.c */; };
23 | 16F0E6871EA4CB6F00365603 /* libhedrot_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 16F0E6851EA4CB6F00365603 /* libhedrot_utils.h */; };
24 | 16F55E0E1EBDAC4800253AEB /* libhedrot_RTmagCalibration.c in Sources */ = {isa = PBXBuildFile; fileRef = 16F55E0C1EBDAC4800253AEB /* libhedrot_RTmagCalibration.c */; };
25 | 16F55E0F1EBDAC4800253AEB /* libhedrot_RTmagCalibration.h in Headers */ = {isa = PBXBuildFile; fileRef = 16F55E0D1EBDAC4800253AEB /* libhedrot_RTmagCalibration.h */; };
26 | /* End PBXBuildFile section */
27 |
28 | /* Begin PBXFileReference section */
29 | 1629E7D21DCBBC70006ACD46 /* hedrot_comm_protocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hedrot_comm_protocol.h; sourceTree = ""; };
30 | 16609A3C1A362064003CC1DC /* hedrot_receiver.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = hedrot_receiver.xcconfig; sourceTree = ""; };
31 | 166427341E9F949D0081EE9E /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/Accelerate.framework; sourceTree = ""; };
32 | 167539AC1EA3A0F60062BDCE /* commonsyms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = commonsyms.c; path = "../../../../SDKs/MaxSDK-6.1.4/c74support/max-includes/common/commonsyms.c"; sourceTree = ""; };
33 | 16904B081EACA9F100517871 /* JitterAPI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JitterAPI.framework; path = "../../../../SDKs/MaxSDK-6.1.4/c74support/jit-includes/JitterAPI.framework"; sourceTree = ""; };
34 | 16904B0A1EACBE1D00517871 /* MaxAudioAPI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MaxAudioAPI.framework; path = "../../../../SDKs/MaxSDK-6.1.4/c74support/msp-includes/MaxAudioAPI.framework"; sourceTree = ""; };
35 | 1695F0041A87997F00708733 /* hedrot_receiver.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hedrot_receiver.c; path = ../source/hedrot_receiver.c; sourceTree = ""; };
36 | 16B2FC6F1DC9F69B003EECB3 /* libhedrot_serialcomm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libhedrot_serialcomm.c; sourceTree = ""; };
37 | 16B2FC701DC9F69B003EECB3 /* libhedrot_serialcomm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libhedrot_serialcomm.h; sourceTree = ""; };
38 | 16B2FC711DC9F69B003EECB3 /* libhedrot.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libhedrot.c; sourceTree = ""; };
39 | 16B2FC721DC9F69B003EECB3 /* libhedrot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libhedrot.h; sourceTree = ""; };
40 | 16B6BF111E193823009E5E99 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
41 | 16DD60A41A5A7879005AE0FF /* hedrot_receiver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = hedrot_receiver.h; path = ../source/hedrot_receiver.h; sourceTree = ""; };
42 | 16F0E6801EA4CAC500365603 /* libhedrot_calibration.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libhedrot_calibration.c; sourceTree = ""; };
43 | 16F0E6811EA4CAC500365603 /* libhedrot_calibration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libhedrot_calibration.h; sourceTree = ""; };
44 | 16F0E6841EA4CB6F00365603 /* libhedrot_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libhedrot_utils.c; sourceTree = ""; };
45 | 16F0E6851EA4CB6F00365603 /* libhedrot_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libhedrot_utils.h; sourceTree = ""; };
46 | 16F55E0C1EBDAC4800253AEB /* libhedrot_RTmagCalibration.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libhedrot_RTmagCalibration.c; sourceTree = ""; };
47 | 16F55E0D1EBDAC4800253AEB /* libhedrot_RTmagCalibration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libhedrot_RTmagCalibration.h; sourceTree = ""; };
48 | 2FBBEAE508F335360078DB84 /* hedrot_receiver.mxo */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = hedrot_receiver.mxo; sourceTree = BUILT_PRODUCTS_DIR; };
49 | /* End PBXFileReference section */
50 |
51 | /* Begin PBXFrameworksBuildPhase section */
52 | 2FBBEADC08F335360078DB84 /* Frameworks */ = {
53 | isa = PBXFrameworksBuildPhase;
54 | buildActionMask = 2147483647;
55 | files = (
56 | 16904B0B1EACBE1D00517871 /* MaxAudioAPI.framework in Frameworks */,
57 | 166427351E9F949D0081EE9E /* Accelerate.framework in Frameworks */,
58 | 16904B091EACA9F100517871 /* JitterAPI.framework in Frameworks */,
59 | );
60 | runOnlyForDeploymentPostprocessing = 0;
61 | };
62 | /* End PBXFrameworksBuildPhase section */
63 |
64 | /* Begin PBXGroup section */
65 | 089C166AFE841209C02AAC07 /* iterator */ = {
66 | isa = PBXGroup;
67 | children = (
68 | 16904B071EACA9D300517871 /* Frameworks */,
69 | 16B6BF111E193823009E5E99 /* Info.plist */,
70 | 1629E7D11DCBBC61006ACD46 /* hedrot-firmware */,
71 | 16B2FC6E1DC9F68E003EECB3 /* libhedrot */,
72 | 1695F0041A87997F00708733 /* hedrot_receiver.c */,
73 | 16DD60A41A5A7879005AE0FF /* hedrot_receiver.h */,
74 | 167539AC1EA3A0F60062BDCE /* commonsyms.c */,
75 | 16609A3C1A362064003CC1DC /* hedrot_receiver.xcconfig */,
76 | 19C28FB4FE9D528D11CA2CBB /* Products */,
77 | );
78 | name = iterator;
79 | sourceTree = "";
80 | };
81 | 1629E7D11DCBBC61006ACD46 /* hedrot-firmware */ = {
82 | isa = PBXGroup;
83 | children = (
84 | 1629E7D21DCBBC70006ACD46 /* hedrot_comm_protocol.h */,
85 | );
86 | name = "hedrot-firmware";
87 | path = "../../firmware/hedrot-firmware";
88 | sourceTree = SOURCE_ROOT;
89 | };
90 | 16904B071EACA9D300517871 /* Frameworks */ = {
91 | isa = PBXGroup;
92 | children = (
93 | 16904B0A1EACBE1D00517871 /* MaxAudioAPI.framework */,
94 | 16904B081EACA9F100517871 /* JitterAPI.framework */,
95 | 166427341E9F949D0081EE9E /* Accelerate.framework */,
96 | );
97 | name = Frameworks;
98 | sourceTree = "";
99 | };
100 | 16B2FC6E1DC9F68E003EECB3 /* libhedrot */ = {
101 | isa = PBXGroup;
102 | children = (
103 | 16B2FC711DC9F69B003EECB3 /* libhedrot.c */,
104 | 16B2FC721DC9F69B003EECB3 /* libhedrot.h */,
105 | 16F0E6801EA4CAC500365603 /* libhedrot_calibration.c */,
106 | 16F0E6811EA4CAC500365603 /* libhedrot_calibration.h */,
107 | 16B2FC6F1DC9F69B003EECB3 /* libhedrot_serialcomm.c */,
108 | 16B2FC701DC9F69B003EECB3 /* libhedrot_serialcomm.h */,
109 | 16F0E6841EA4CB6F00365603 /* libhedrot_utils.c */,
110 | 16F0E6851EA4CB6F00365603 /* libhedrot_utils.h */,
111 | 16F55E0C1EBDAC4800253AEB /* libhedrot_RTmagCalibration.c */,
112 | 16F55E0D1EBDAC4800253AEB /* libhedrot_RTmagCalibration.h */,
113 | );
114 | name = libhedrot;
115 | path = ../../libhedrot;
116 | sourceTree = "";
117 | };
118 | 19C28FB4FE9D528D11CA2CBB /* Products */ = {
119 | isa = PBXGroup;
120 | children = (
121 | 2FBBEAE508F335360078DB84 /* hedrot_receiver.mxo */,
122 | );
123 | name = Products;
124 | sourceTree = "";
125 | };
126 | /* End PBXGroup section */
127 |
128 | /* Begin PBXHeadersBuildPhase section */
129 | 2FBBEAD708F335360078DB84 /* Headers */ = {
130 | isa = PBXHeadersBuildPhase;
131 | buildActionMask = 2147483647;
132 | files = (
133 | 1629E7D31DCBBC70006ACD46 /* hedrot_comm_protocol.h in Headers */,
134 | 16F0E6831EA4CAC500365603 /* libhedrot_calibration.h in Headers */,
135 | 16B2FC761DC9F69B003EECB3 /* libhedrot.h in Headers */,
136 | 16F0E6871EA4CB6F00365603 /* libhedrot_utils.h in Headers */,
137 | 16B2FC741DC9F69B003EECB3 /* libhedrot_serialcomm.h in Headers */,
138 | 16F55E0F1EBDAC4800253AEB /* libhedrot_RTmagCalibration.h in Headers */,
139 | );
140 | runOnlyForDeploymentPostprocessing = 0;
141 | };
142 | /* End PBXHeadersBuildPhase section */
143 |
144 | /* Begin PBXNativeTarget section */
145 | 2FBBEAD608F335360078DB84 /* max-external */ = {
146 | isa = PBXNativeTarget;
147 | buildConfigurationList = 2FBBEAE008F335360078DB84 /* Build configuration list for PBXNativeTarget "max-external" */;
148 | buildPhases = (
149 | 2FBBEAD708F335360078DB84 /* Headers */,
150 | 2FBBEAD808F335360078DB84 /* Resources */,
151 | 2FBBEADA08F335360078DB84 /* Sources */,
152 | 2FBBEADC08F335360078DB84 /* Frameworks */,
153 | 2FBBEADF08F335360078DB84 /* Rez */,
154 | );
155 | buildRules = (
156 | );
157 | dependencies = (
158 | );
159 | name = "max-external";
160 | productName = iterator;
161 | productReference = 2FBBEAE508F335360078DB84 /* hedrot_receiver.mxo */;
162 | productType = "com.apple.product-type.bundle";
163 | };
164 | /* End PBXNativeTarget section */
165 |
166 | /* Begin PBXProject section */
167 | 089C1669FE841209C02AAC07 /* Project object */ = {
168 | isa = PBXProject;
169 | attributes = {
170 | LastUpgradeCheck = 0820;
171 | };
172 | buildConfigurationList = 2FBBEACF08F335010078DB84 /* Build configuration list for PBXProject "hedrot_receiver" */;
173 | compatibilityVersion = "Xcode 3.2";
174 | developmentRegion = English;
175 | hasScannedForEncodings = 1;
176 | knownRegions = (
177 | en,
178 | );
179 | mainGroup = 089C166AFE841209C02AAC07 /* iterator */;
180 | projectDirPath = "";
181 | projectRoot = "";
182 | targets = (
183 | 2FBBEAD608F335360078DB84 /* max-external */,
184 | );
185 | };
186 | /* End PBXProject section */
187 |
188 | /* Begin PBXResourcesBuildPhase section */
189 | 2FBBEAD808F335360078DB84 /* Resources */ = {
190 | isa = PBXResourcesBuildPhase;
191 | buildActionMask = 2147483647;
192 | files = (
193 | );
194 | runOnlyForDeploymentPostprocessing = 0;
195 | };
196 | /* End PBXResourcesBuildPhase section */
197 |
198 | /* Begin PBXRezBuildPhase section */
199 | 2FBBEADF08F335360078DB84 /* Rez */ = {
200 | isa = PBXRezBuildPhase;
201 | buildActionMask = 2147483647;
202 | files = (
203 | );
204 | runOnlyForDeploymentPostprocessing = 0;
205 | };
206 | /* End PBXRezBuildPhase section */
207 |
208 | /* Begin PBXSourcesBuildPhase section */
209 | 2FBBEADA08F335360078DB84 /* Sources */ = {
210 | isa = PBXSourcesBuildPhase;
211 | buildActionMask = 2147483647;
212 | files = (
213 | 1695F0051A87997F00708733 /* hedrot_receiver.c in Sources */,
214 | 16B2FC731DC9F69B003EECB3 /* libhedrot_serialcomm.c in Sources */,
215 | 167539AD1EA3A0F60062BDCE /* commonsyms.c in Sources */,
216 | 16F0E6861EA4CB6F00365603 /* libhedrot_utils.c in Sources */,
217 | 16B2FC751DC9F69B003EECB3 /* libhedrot.c in Sources */,
218 | 16F55E0E1EBDAC4800253AEB /* libhedrot_RTmagCalibration.c in Sources */,
219 | 16F0E6821EA4CAC500365603 /* libhedrot_calibration.c in Sources */,
220 | );
221 | runOnlyForDeploymentPostprocessing = 0;
222 | };
223 | /* End PBXSourcesBuildPhase section */
224 |
225 | /* Begin XCBuildConfiguration section */
226 | 2FBBEAD008F335010078DB84 /* Development */ = {
227 | isa = XCBuildConfiguration;
228 | baseConfigurationReference = 16609A3C1A362064003CC1DC /* hedrot_receiver.xcconfig */;
229 | buildSettings = {
230 | CLANG_WARN_BOOL_CONVERSION = YES;
231 | CLANG_WARN_CONSTANT_CONVERSION = YES;
232 | CLANG_WARN_EMPTY_BODY = YES;
233 | CLANG_WARN_ENUM_CONVERSION = YES;
234 | CLANG_WARN_INFINITE_RECURSION = YES;
235 | CLANG_WARN_INT_CONVERSION = YES;
236 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
237 | CLANG_WARN_UNREACHABLE_CODE = YES;
238 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
239 | ENABLE_STRICT_OBJC_MSGSEND = YES;
240 | ENABLE_TESTABILITY = YES;
241 | GCC_NO_COMMON_BLOCKS = YES;
242 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
243 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
244 | GCC_WARN_UNDECLARED_SELECTOR = YES;
245 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
246 | GCC_WARN_UNUSED_FUNCTION = YES;
247 | GCC_WARN_UNUSED_VARIABLE = YES;
248 | ONLY_ACTIVE_ARCH = NO;
249 | SDKROOT = macosx10.9;
250 | };
251 | name = Development;
252 | };
253 | 2FBBEAD108F335010078DB84 /* Deployment */ = {
254 | isa = XCBuildConfiguration;
255 | baseConfigurationReference = 16609A3C1A362064003CC1DC /* hedrot_receiver.xcconfig */;
256 | buildSettings = {
257 | CLANG_WARN_BOOL_CONVERSION = YES;
258 | CLANG_WARN_CONSTANT_CONVERSION = YES;
259 | CLANG_WARN_EMPTY_BODY = YES;
260 | CLANG_WARN_ENUM_CONVERSION = YES;
261 | CLANG_WARN_INFINITE_RECURSION = YES;
262 | CLANG_WARN_INT_CONVERSION = YES;
263 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
264 | CLANG_WARN_UNREACHABLE_CODE = YES;
265 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
266 | ENABLE_STRICT_OBJC_MSGSEND = YES;
267 | GCC_NO_COMMON_BLOCKS = YES;
268 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
269 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
270 | GCC_WARN_UNDECLARED_SELECTOR = YES;
271 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
272 | GCC_WARN_UNUSED_FUNCTION = YES;
273 | GCC_WARN_UNUSED_VARIABLE = YES;
274 | ONLY_ACTIVE_ARCH = NO;
275 | SDKROOT = macosx10.9;
276 | };
277 | name = Deployment;
278 | };
279 | 2FBBEAE108F335360078DB84 /* Development */ = {
280 | isa = XCBuildConfiguration;
281 | baseConfigurationReference = 16609A3C1A362064003CC1DC /* hedrot_receiver.xcconfig */;
282 | buildSettings = {
283 | COMBINE_HIDPI_IMAGES = YES;
284 | COPY_PHASE_STRIP = NO;
285 | FRAMEWORK_SEARCH_PATHS = (
286 | "$(inherited)",
287 | "/Volumes/Data/Developpement/SDKs/MaxSDK-6.1.4/c74support/jit-includes",
288 | "/Volumes/Data/Developpement/SDKs/MaxSDK-6.1.4/c74support/msp-includes",
289 | );
290 | GCC_OPTIMIZATION_LEVEL = 0;
291 | INFOPLIST_PREFIX_HEADER = "";
292 | INFOPLIST_PREPROCESS = NO;
293 | OTHER_LDFLAGS = "$(C74_SYM_LINKER_FLAGS)";
294 | PRODUCT_BUNDLE_IDENTIFIER = "com.hedrot.${PRODUCT_NAME:rfc1034identifier}";
295 | PRODUCT_NAME = hedrot_receiver;
296 | };
297 | name = Development;
298 | };
299 | 2FBBEAE208F335360078DB84 /* Deployment */ = {
300 | isa = XCBuildConfiguration;
301 | baseConfigurationReference = 16609A3C1A362064003CC1DC /* hedrot_receiver.xcconfig */;
302 | buildSettings = {
303 | COMBINE_HIDPI_IMAGES = YES;
304 | COPY_PHASE_STRIP = YES;
305 | FRAMEWORK_SEARCH_PATHS = (
306 | "$(inherited)",
307 | "/Volumes/Data/Developpement/SDKs/MaxSDK-6.1.4/c74support/jit-includes",
308 | "/Volumes/Data/Developpement/SDKs/MaxSDK-6.1.4/c74support/msp-includes",
309 | );
310 | INFOPLIST_PREFIX_HEADER = "";
311 | INFOPLIST_PREPROCESS = NO;
312 | OTHER_LDFLAGS = "$(C74_SYM_LINKER_FLAGS)";
313 | PRODUCT_BUNDLE_IDENTIFIER = "com.hedrot.${PRODUCT_NAME:rfc1034identifier}";
314 | PRODUCT_NAME = hedrot_receiver;
315 | };
316 | name = Deployment;
317 | };
318 | /* End XCBuildConfiguration section */
319 |
320 | /* Begin XCConfigurationList section */
321 | 2FBBEACF08F335010078DB84 /* Build configuration list for PBXProject "hedrot_receiver" */ = {
322 | isa = XCConfigurationList;
323 | buildConfigurations = (
324 | 2FBBEAD008F335010078DB84 /* Development */,
325 | 2FBBEAD108F335010078DB84 /* Deployment */,
326 | );
327 | defaultConfigurationIsVisible = 0;
328 | defaultConfigurationName = Development;
329 | };
330 | 2FBBEAE008F335360078DB84 /* Build configuration list for PBXNativeTarget "max-external" */ = {
331 | isa = XCConfigurationList;
332 | buildConfigurations = (
333 | 2FBBEAE108F335360078DB84 /* Development */,
334 | 2FBBEAE208F335360078DB84 /* Deployment */,
335 | );
336 | defaultConfigurationIsVisible = 0;
337 | defaultConfigurationName = Development;
338 | };
339 | /* End XCConfigurationList section */
340 | };
341 | rootObject = 089C1669FE841209C02AAC07 /* Project object */;
342 | }
343 |
--------------------------------------------------------------------------------