diff --git a/ShimmerBluetooth/ShimmerBluetooth.xcodeproj/project.pbxproj b/ShimmerBluetooth/ShimmerBluetooth.xcodeproj/project.pbxproj index e480098..15f0edf 100644 --- a/ShimmerBluetooth/ShimmerBluetooth.xcodeproj/project.pbxproj +++ b/ShimmerBluetooth/ShimmerBluetooth.xcodeproj/project.pbxproj @@ -37,6 +37,7 @@ 3AED206D2B0B10960066A0F8 /* ShimmerUtilitiesTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AED206C2B0B10960066A0F8 /* ShimmerUtilitiesTest.swift */; }; 3AED20712B0C4BA60066A0F8 /* MagSensor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AED20702B0C4BA60066A0F8 /* MagSensor.swift */; }; 3AED20732B0C587B0066A0F8 /* GyroSensor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AED20722B0C587B0066A0F8 /* GyroSensor.swift */; }; + 92150EF52DE461CE00FEA53B /* AltMagSensor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92150EF42DE461CE00FEA53B /* AltMagSensor.swift */; }; 9299E50E2B85054E001EEFE0 /* PressureTempSensor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9299E50D2B85054E001EEFE0 /* PressureTempSensor.swift */; }; 9299E5102B850571001EEFE0 /* BattVoltageSensor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9299E50F2B850571001EEFE0 /* BattVoltageSensor.swift */; }; 92B1067A2B7DAFBC00AB9952 /* EXGSensor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92B106792B7DAFBC00AB9952 /* EXGSensor.swift */; }; @@ -84,6 +85,7 @@ 3AED206C2B0B10960066A0F8 /* ShimmerUtilitiesTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShimmerUtilitiesTest.swift; sourceTree = ""; }; 3AED20702B0C4BA60066A0F8 /* MagSensor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MagSensor.swift; sourceTree = ""; }; 3AED20722B0C587B0066A0F8 /* GyroSensor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GyroSensor.swift; sourceTree = ""; }; + 92150EF42DE461CE00FEA53B /* AltMagSensor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AltMagSensor.swift; sourceTree = ""; }; 9299E50D2B85054E001EEFE0 /* PressureTempSensor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PressureTempSensor.swift; sourceTree = ""; }; 9299E50F2B850571001EEFE0 /* BattVoltageSensor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BattVoltageSensor.swift; sourceTree = ""; }; 92B106792B7DAFBC00AB9952 /* EXGSensor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EXGSensor.swift; sourceTree = ""; }; @@ -131,6 +133,7 @@ 3A780C872AE12BEB00EAF050 /* ShimmerBluetooth */ = { isa = PBXGroup; children = ( + 92150EF42DE461CE00FEA53B /* AltMagSensor.swift */, 3AEB12F82BCE6F7E00B5F6F1 /* Shimmer3SpeedTestProtocol.swift */, 3A780C882AE12BEB00EAF050 /* ShimmerBluetooth.h */, 3A780C892AE12BEB00EAF050 /* ShimmerBluetooth.docc */, @@ -299,6 +302,7 @@ 3AB320E62B070830003D94F8 /* Sensor.swift in Sources */, 3A0B4B672B0EE42700786295 /* IMUSensor.swift in Sources */, 3A1CBAD32AE2DD1C00BC1E54 /* BleByteRadio.swift in Sources */, + 92150EF52DE461CE00FEA53B /* AltMagSensor.swift in Sources */, 3A7712912AE26805006213A8 /* BLEByteRadioold.swift in Sources */, 3A77128D2AE177A4006213A8 /* ShimmerDevice.swift in Sources */, 3AA359152AF37943008AD334 /* ConfigByteLayoutShimmer3.swift in Sources */, diff --git a/ShimmerBluetooth/ShimmerBluetooth/AltMagSensor.swift b/ShimmerBluetooth/ShimmerBluetooth/AltMagSensor.swift new file mode 100644 index 0000000..326e51e --- /dev/null +++ b/ShimmerBluetooth/ShimmerBluetooth/AltMagSensor.swift @@ -0,0 +1,245 @@ +// +// AltMagSensor.swift +// ShimmerBluetooth +// +// Created by Shimmer Engineering on 26/05/2025. +// + +import Foundation + +public class AltMagSensor : IMUSensor , SensorProcessing{ + + public enum Range3R: UInt8 { + case RANGE_4Ga = 0x0 + case RANGE_8Ga = 0x1 + case RANGE_12Ga = 0x2 + case RANGE_16Ga = 0x3 + + public static func fromValue(_ value : UInt8) -> Range3R? { + switch value{ + case 0: + return .RANGE_4Ga + case 1: + return .RANGE_8Ga + case 2: + return .RANGE_12Ga + case 3: + return .RANGE_16Ga + default: + return nil + } + } + } + var Current3RRange = Range3R.RANGE_4Ga + + public var packetIndexAltMagX:Int = -1 + public var packetIndexAltMagY:Int = -1 + public var packetIndexAltMagZ:Int = -1 + public static let ALT_MAGNETOMETER_X = "Alt Magnetometer X" + public static let ALT_MAGNETOMETER_Y = "Alt Magnetometer Y" + public static let ALT_MAGNETOMETER_Z = "Alt Magnetometer Z" + var calibBytes_4Ga: [UInt8] = [] + var calibBytes_8Ga: [UInt8] = [] + var calibBytes_12Ga: [UInt8] = [] + var calibBytes_16Ga: [UInt8] = [] + var altMagRange = 0 + var CALIBRATION_ID = 41 + var AlignmentMatrix : [[Double]] = [[]] + var SensitivityMatrix : [[Double]] = [[]] + var OffsetVector : [Double] = [] + var AlignmentMatrix_4Ga:[[Double]] = [[]] + var SensitivityMatrix_4Ga:[[Double]] = [[]] + var OffsetVector_4Ga:[Double]=[] + var AlignmentMatrix_8Ga:[[Double]] = [[]] + var SensitivityMatrix_8Ga:[[Double]] = [[]] + var OffsetVector_8Ga:[Double]=[] + var AlignmentMatrix_12Ga:[[Double]] = [[]] + var SensitivityMatrix_12Ga:[[Double]] = [[]] + var OffsetVector_12Ga:[Double]=[] + var AlignmentMatrix_16Ga:[[Double]] = [[]] + var SensitivityMatrix_16Ga:[[Double]] = [[]] + var OffsetVector_16Ga:[Double]=[] + + public func get3RRange()->Range3R{ + return Current3RRange + } + + public func processData(sensorPacket: [UInt8], objectCluster: ObjectCluster) -> ObjectCluster { + let x = Array(sensorPacket[packetIndexAltMagX..>ConfigByteLayoutShimmer3.bitShiftLSM303DLHCMagRange) & 1 + if (enabled == 1){ + sensorEnabled = true + } else { + sensorEnabled = false + } + altMagRange = (Int(infomem[ConfigByteLayoutShimmer3.idxConfigSetupByte2] >> ConfigByteLayoutShimmer3.bitShiftLSM303DLHCMagRange) & ConfigByteLayoutShimmer3.maskLSM303DLHCMagRange) + + if(HardwareVersion == Shimmer3Protocol.HardwareType.Shimmer3R.rawValue){ + if (altMagRange == 0){ + Current3RRange = Range3R.RANGE_4Ga + AlignmentMatrix = AlignmentMatrix_4Ga + SensitivityMatrix = SensitivityMatrix_4Ga + OffsetVector = OffsetVector_4Ga + } + if (altMagRange == 1){ + Current3RRange = Range3R.RANGE_8Ga + AlignmentMatrix = AlignmentMatrix_8Ga + SensitivityMatrix = SensitivityMatrix_8Ga + OffsetVector = OffsetVector_8Ga + } + if (altMagRange == 2){ + Current3RRange = Range3R.RANGE_12Ga + AlignmentMatrix = AlignmentMatrix_12Ga + SensitivityMatrix = SensitivityMatrix_12Ga + OffsetVector = OffsetVector_12Ga + } + if (altMagRange == 3){ + Current3RRange = Range3R.RANGE_16Ga + AlignmentMatrix = AlignmentMatrix_16Ga + SensitivityMatrix = SensitivityMatrix_16Ga + OffsetVector = OffsetVector_16Ga + } + } + } + + public func setLowPowerAltMag(enable: Bool, isShimmer3withUpdatedSensors: Bool, isShimmer3Sensor: Bool, samplingRate: Double, infomem: [UInt8])-> [UInt8]{ + let LowPowerMagEnabled = enable + var infomemtoupdate = infomem + if(HardwareVersion == Shimmer3Protocol.HardwareType.Shimmer3R.rawValue){ + if(!LowPowerMagEnabled){ + if(samplingRate > 560){ + infomemtoupdate = updateInfoMemAltMagRate(infomem: infomem, magRate:0x01) + }else if(samplingRate > 300){ + infomemtoupdate = updateInfoMemAltMagRate(infomem: infomem, magRate:0x11) + }else if(samplingRate > 155){ + infomemtoupdate = updateInfoMemAltMagRate(infomem: infomem, magRate:0x21) + }else if(samplingRate > 100){ + infomemtoupdate = updateInfoMemAltMagRate(infomem: infomem, magRate:0x31) + }else if(samplingRate > 50){ + infomemtoupdate = updateInfoMemAltMagRate(infomem: infomem, magRate:0x31) + }else if(samplingRate > 20){ + infomemtoupdate = updateInfoMemAltMagRate(infomem: infomem, magRate:0x3E) + }else if(samplingRate > 10){ + infomemtoupdate = updateInfoMemAltMagRate(infomem: infomem, magRate:0x3A) + }else{ + infomemtoupdate = updateInfoMemAltMagRate(infomem: infomem, magRate:0x08) + } + }else{ + infomemtoupdate = updateInfoMemAltMagRate(infomem: infomem, magRate:0x08) + } + } + return infomemtoupdate + + } + + public func updateInfoMem3RAltMagRange(infomem: [UInt8],range: Range3R) -> [UInt8]{ + var infomemtoupdate = infomem + print("oriinfomem: \(infomemtoupdate)") + var altMagRange = 0 + var calibBytes = calibBytes_4Ga + if (range == Range3R.RANGE_4Ga){ + altMagRange = 0 + calibBytes = calibBytes_4Ga + }else if (range == Range3R.RANGE_8Ga){ + altMagRange = 1 + calibBytes = calibBytes_8Ga + } else if (range == Range3R.RANGE_12Ga){ + altMagRange = 2 + calibBytes = calibBytes_12Ga + } else if (range == Range3R.RANGE_16Ga){ + altMagRange = 3 + calibBytes = calibBytes_16Ga + } + + infomemtoupdate.replaceSubrange( + ConfigByteLayoutShimmer3.idxLIS3MDLAltMagCalibration.. [UInt8]{ + var infomemtoupdate = infomem + + print("oriinfomem : \(infomemtoupdate)") + + let orivalue = infomemtoupdate[ConfigByteLayoutShimmer3.idxConfigSetupByte2] + let value = infomemtoupdate[ConfigByteLayoutShimmer3.idxConfigSetupByte2] & ~UInt8(ConfigByteLayoutShimmer3.maskLSM303DLHCMagSamplingRate<? public static let VERISENSE_RBL_SERVICE_UUID = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" public static let VERISENSE_RBL_CHAR_RX_UUID = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" @@ -17,6 +18,12 @@ public class BleByteRadio : NSObject, ByteCommunication { public static let SHIMMER3_RBL_SERVICE_UUID = "49535343-FE7D-4AE5-8FA9-9FAFD205E455" public static let SHIMMER3_RBL_CHAR_RX_UUID = "49535343-1E4D-4BD9-BA61-23C647249616" public static let SHIMMER3_RBL_CHAR_TX_UUID = "49535343-8841-43F4-A8D4-ECBE34729BB3" + + public static let SHIMMER3R_RBL_SERVICE_UUID = "65333333-A115-11E2-9E9A-0800200CA100" + public static let SHIMMER3R_RBL_CHAR_RX_UUID = "65333333-A115-11E2-9E9A-0800200CA102" + public static let SHIMMER3R_RBL_CHAR_TX_UUID = "65333333-A115-11E2-9E9A-0800200CA101" + + public var deviceName: String? public var delegate: ByteCommunicationDelegate? @@ -38,7 +45,11 @@ public class BleByteRadio : NSObject, ByteCommunication { RBL_SERVICE_UUID = BleByteRadio.VERISENSE_RBL_SERVICE_UUID RBL_CHAR_RX_UUID = BleByteRadio.VERISENSE_RBL_CHAR_RX_UUID RBL_CHAR_TX_UUID = BleByteRadio.VERISENSE_RBL_CHAR_TX_UUID - } else if let isActive = self.activePeripheral?.name?.contains(BleByteRadio.SHIMMER), isActive { + } else if let isActive = self.activePeripheral?.name?.contains(BleByteRadio.SHIMMER3R), isActive { + RBL_SERVICE_UUID = BleByteRadio.SHIMMER3R_RBL_SERVICE_UUID + RBL_CHAR_RX_UUID = BleByteRadio.SHIMMER3R_RBL_CHAR_RX_UUID + RBL_CHAR_TX_UUID = BleByteRadio.SHIMMER3R_RBL_CHAR_TX_UUID + } else if let isActive = self.activePeripheral?.name?.contains(BleByteRadio.SHIMMER3), isActive { RBL_SERVICE_UUID = BleByteRadio.SHIMMER3_RBL_SERVICE_UUID RBL_CHAR_RX_UUID = BleByteRadio.SHIMMER3_RBL_CHAR_RX_UUID RBL_CHAR_TX_UUID = BleByteRadio.SHIMMER3_RBL_CHAR_TX_UUID diff --git a/ShimmerBluetooth/ShimmerBluetooth/ConfigByteLayoutShimmer3.swift b/ShimmerBluetooth/ShimmerBluetooth/ConfigByteLayoutShimmer3.swift index 8711694..5169ef9 100644 --- a/ShimmerBluetooth/ShimmerBluetooth/ConfigByteLayoutShimmer3.swift +++ b/ShimmerBluetooth/ShimmerBluetooth/ConfigByteLayoutShimmer3.swift @@ -40,8 +40,12 @@ public class ConfigByteLayoutShimmer3{ static let idxBtCommBaudRate = 30 static let idxAnalogAccelCalibration = 31 static let idxMPU9150GyroCalibration = 52 - static let idxLSM303DLHCMagCalibration = 73 - static let idxLSM303DLHCAccelCalibration = 94 //94->114 + static let idxLSM303DLHCMagCalibration = 76 + static let idxLIS3MDLAltMagCalibration = 285 + + //static let idxLSM303DLHCAccelCalibration = 94 //94->114 + static let idxConfigSetupByte4 = 128+2; + static let idxSDExperimentConfig0 = 128+89; static let idxSDExperimentConfig1 = 128+90; @@ -51,6 +55,9 @@ public class ConfigByteLayoutShimmer3{ static let bitShiftMPU9150GyroRange = 0; static let maskMPU9150GyroRange = 0x03; + static let bitShiftLSM6DSVyroRangeMSB = 2; + static let maskLSM6DSVyroRangeMSB = 0x01; + static let bitShiftMPU9150AccelGyroSamplingRate = 0; static let maskMPU9150AccelGyroSamplingRate = 0xFF; @@ -63,12 +70,21 @@ public class ConfigByteLayoutShimmer3{ static let bitShiftLSM303DLHCMagRange = 5; static let maskLSM303DLHCMagRange = 0x07; + static let bitShiftMPU9150AccelRange = 6; + static let maskMPU9150AccelRange = 0x03; + static let bitShiftLSM303DLHCMagSamplingRate = 2; static let maskLSM303DLHCMagSamplingRate = 0x07; static let bitShiftLSM303DLHCAccelSamplingRate = 4; static let maskLSM303DLHCAccelSamplingRate = 0x0F; + static let idxLSM6DSVAccelCalibration = 34; + static let idxGyroCalibration = 55; + static let idxLSM303DLHCAccelCalibration = 97; + + static let lengthGeneralCalibrationBytes = 21; + static let bitShiftRTCError = 4; static let maskRTCError = 1; } diff --git a/ShimmerBluetooth/ShimmerBluetooth/GyroSensor.swift b/ShimmerBluetooth/ShimmerBluetooth/GyroSensor.swift index 72196bb..be77749 100644 --- a/ShimmerBluetooth/ShimmerBluetooth/GyroSensor.swift +++ b/ShimmerBluetooth/ShimmerBluetooth/GyroSensor.swift @@ -31,15 +31,49 @@ public class GyroSensor : IMUSensor , SensorProcessing{ } } - var CurrentRange = Range.RANGE_250DPS + public enum Range3R: UInt8 { + case RANGE_125DPS = 0x0 + case RANGE_250DPS = 0x1 + case RANGE_500DPS = 0x2 + case RANGE_1000DPS = 0x3 + case RANGE_2000DPS = 0x4 + case RANGE_4000DPS = 0x5 + + public static func fromValue(_ value : UInt8) -> Range3R? { + switch value{ + case 0: + return .RANGE_125DPS + case 1: + return .RANGE_250DPS + case 2: + return .RANGE_500DPS + case 3: + return .RANGE_1000DPS + case 4: + return .RANGE_2000DPS + case 5: + return .RANGE_4000DPS + default: + return nil + } + } + } + + var CurrentRange = Range.RANGE_250DPS + var Current3RRange = Range3R.RANGE_250DPS + + public var packetIndexGyroX:Int = -1 public var packetIndexGyroY:Int = -1 public var packetIndexGyroZ:Int = -1 public static let GYROSCOPE_X = "Gyroscope X" public static let GYROSCOPE_Y = "Gyroscope Y" public static let GYROSCOPE_Z = "Gyroscope Z" - let CALIBRATION_ID = 30 + var CALIBRATION_ID = 30 + var AlignmentMatrix_125DPS:[[Double]] = [[]] + var SensitivityMatrix_125DPS:[[Double]] = [[]] + var OffsetVector_125DPS:[Double]=[] var AlignmentMatrix_250DPS:[[Double]] = [[]] var SensitivityMatrix_250DPS:[[Double]] = [[]] var OffsetVector_250DPS:[Double]=[] @@ -52,18 +86,40 @@ public class GyroSensor : IMUSensor , SensorProcessing{ var AlignmentMatrix_2000DPS:[[Double]] = [[]] var SensitivityMatrix_2000DPS:[[Double]] = [[]] var OffsetVector_2000DPS:[Double]=[] + var AlignmentMatrix_4000DPS:[[Double]] = [[]] + var SensitivityMatrix_4000DPS:[[Double]] = [[]] + var OffsetVector_4000DPS:[Double]=[] + var gyroRange = 1 var AlignmentMatrix : [[Double]] = [[]] var SensitivityMatrix : [[Double]] = [[]] var OffsetVector : [Double] = [] + var calibBytes_125DPS: [UInt8] = [] + var calibBytes_250DPS: [UInt8] = [] + var calibBytes_500DPS: [UInt8] = [] + var calibBytes_1000DPS: [UInt8] = [] + var calibBytes_2000DPS: [UInt8] = [] + var calibBytes_4000DPS: [UInt8] = [] + public func processData(sensorPacket: [UInt8], objectCluster: ObjectCluster) -> ObjectCluster { let x = Array(sensorPacket[packetIndexGyroX.. [UInt8]{ var infomemtoupdate = infomem print("oriinfomem: \(infomemtoupdate)") + var gyroRange = 0 + var calibBytes = calibBytes_250DPS + if (range == Range.RANGE_250DPS){ + gyroRange = 0 + calibBytes = calibBytes_250DPS + } else if (range == Range.RANGE_500DPS){ + gyroRange = 1 + calibBytes = calibBytes_500DPS + } else if (range == Range.RANGE_1000DPS){ + gyroRange = 2 + calibBytes = calibBytes_1000DPS + } else if (range == Range.RANGE_2000DPS){ + gyroRange = 3 + calibBytes = calibBytes_2000DPS + } + + + infomemtoupdate.replaceSubrange( + ConfigByteLayoutShimmer3.idxGyroCalibration.. [UInt8]{ + var infomemtoupdate = infomem + print("oriinfomem: \(infomemtoupdate)") var gyroRange = 0 - if (range == Range.RANGE_250DPS){ + var calibBytes = calibBytes_125DPS + if (range == Range3R.RANGE_125DPS){ gyroRange = 0 - } else if (range == Range.RANGE_500DPS){ + calibBytes = calibBytes_125DPS + }else if (range == Range3R.RANGE_250DPS){ gyroRange = 1 - } else if (range == Range.RANGE_1000DPS){ + calibBytes = calibBytes_250DPS + } else if (range == Range3R.RANGE_500DPS){ gyroRange = 2 - } else if (range == Range.RANGE_2000DPS){ + calibBytes = calibBytes_500DPS + } else if (range == Range3R.RANGE_1000DPS){ gyroRange = 3 + calibBytes = calibBytes_1000DPS + } else if (range == Range3R.RANGE_2000DPS){ + gyroRange = 4 + calibBytes = calibBytes_2000DPS + }else if (range == Range3R.RANGE_4000DPS){ + gyroRange = 5 + calibBytes = calibBytes_4000DPS } + + + infomemtoupdate.replaceSubrange( + ConfigByteLayoutShimmer3.idxGyroCalibration..>2)<Range{ return CurrentRange } + public func get3RRange()->Range3R{ + return Current3RRange + } + public func setInfoMem(infomem: [UInt8]) { var enabled = Int(infomem[ConfigByteLayoutShimmer3.idxSensors0]>>6) & 1 @@ -148,30 +319,73 @@ public class GyroSensor : IMUSensor , SensorProcessing{ sensorEnabled = false } - gyroRange = (Int(infomem[ConfigByteLayoutShimmer3.idxConfigSetupByte2] >> ConfigByteLayoutShimmer3.bitShiftMPU9150GyroRange) & ConfigByteLayoutShimmer3.maskMPU9150GyroRange) - if (gyroRange == 0){ - CurrentRange = Range.RANGE_250DPS - AlignmentMatrix = AlignmentMatrix_250DPS - SensitivityMatrix = SensitivityMatrix_250DPS - OffsetVector = OffsetVector_250DPS - } - if (gyroRange == 1){ - CurrentRange = Range.RANGE_500DPS - AlignmentMatrix = AlignmentMatrix_500DPS - SensitivityMatrix = SensitivityMatrix_500DPS - OffsetVector = OffsetVector_500DPS - } - if (gyroRange == 2){ - CurrentRange = Range.RANGE_1000DPS - AlignmentMatrix = AlignmentMatrix_1000DPS - SensitivityMatrix = SensitivityMatrix_1000DPS - OffsetVector = OffsetVector_1000DPS - } - if (gyroRange == 3){ - CurrentRange = Range.RANGE_2000DPS - AlignmentMatrix = AlignmentMatrix_2000DPS - SensitivityMatrix = SensitivityMatrix_2000DPS - OffsetVector = OffsetVector_2000DPS + if(HardwareVersion == Shimmer3Protocol.HardwareType.Shimmer3.rawValue){ + gyroRange = (Int(infomem[ConfigByteLayoutShimmer3.idxConfigSetupByte2] >> ConfigByteLayoutShimmer3.bitShiftMPU9150GyroRange) & ConfigByteLayoutShimmer3.maskMPU9150GyroRange) + if (gyroRange == 0){ + CurrentRange = Range.RANGE_250DPS + AlignmentMatrix = AlignmentMatrix_250DPS + SensitivityMatrix = SensitivityMatrix_250DPS + OffsetVector = OffsetVector_250DPS + } + if (gyroRange == 1){ + CurrentRange = Range.RANGE_500DPS + AlignmentMatrix = AlignmentMatrix_500DPS + SensitivityMatrix = SensitivityMatrix_500DPS + OffsetVector = OffsetVector_500DPS + } + if (gyroRange == 2){ + CurrentRange = Range.RANGE_1000DPS + AlignmentMatrix = AlignmentMatrix_1000DPS + SensitivityMatrix = SensitivityMatrix_1000DPS + OffsetVector = OffsetVector_1000DPS + } + if (gyroRange == 3){ + CurrentRange = Range.RANGE_2000DPS + AlignmentMatrix = AlignmentMatrix_2000DPS + SensitivityMatrix = SensitivityMatrix_2000DPS + OffsetVector = OffsetVector_2000DPS + } + }else if(HardwareVersion == Shimmer3Protocol.HardwareType.Shimmer3R.rawValue){ + let gyroRangeLSB = (Int(infomem[ConfigByteLayoutShimmer3.idxConfigSetupByte2] >> ConfigByteLayoutShimmer3.bitShiftMPU9150GyroRange) & ConfigByteLayoutShimmer3.maskMPU9150GyroRange) + let gyroRangeMSB = (Int(infomem[ConfigByteLayoutShimmer3.idxConfigSetupByte4] >> ConfigByteLayoutShimmer3.bitShiftLSM6DSVyroRangeMSB) & ConfigByteLayoutShimmer3.maskLSM6DSVyroRangeMSB) + + gyroRange = ((gyroRangeMSB<<2) | gyroRangeLSB) + if (gyroRange == 0){ + Current3RRange = Range3R.RANGE_125DPS + AlignmentMatrix = AlignmentMatrix_125DPS + SensitivityMatrix = SensitivityMatrix_125DPS + OffsetVector = OffsetVector_125DPS + } + if (gyroRange == 1){ + Current3RRange = Range3R.RANGE_250DPS + AlignmentMatrix = AlignmentMatrix_250DPS + SensitivityMatrix = SensitivityMatrix_250DPS + OffsetVector = OffsetVector_250DPS + } + if (gyroRange == 2){ + Current3RRange = Range3R.RANGE_500DPS + AlignmentMatrix = AlignmentMatrix_500DPS + SensitivityMatrix = SensitivityMatrix_500DPS + OffsetVector = OffsetVector_500DPS + } + if (gyroRange == 3){ + Current3RRange = Range3R.RANGE_1000DPS + AlignmentMatrix = AlignmentMatrix_1000DPS + SensitivityMatrix = SensitivityMatrix_1000DPS + OffsetVector = OffsetVector_1000DPS + } + if (gyroRange == 4){ + Current3RRange = Range3R.RANGE_2000DPS + AlignmentMatrix = AlignmentMatrix_2000DPS + SensitivityMatrix = SensitivityMatrix_2000DPS + OffsetVector = OffsetVector_2000DPS + } + if (gyroRange == 5){ + Current3RRange = Range3R.RANGE_4000DPS + AlignmentMatrix = AlignmentMatrix_4000DPS + SensitivityMatrix = SensitivityMatrix_4000DPS + OffsetVector = OffsetVector_4000DPS + } } } diff --git a/ShimmerBluetooth/ShimmerBluetooth/IMUSensor.swift b/ShimmerBluetooth/ShimmerBluetooth/IMUSensor.swift index 4156329..51716b3 100644 --- a/ShimmerBluetooth/ShimmerBluetooth/IMUSensor.swift +++ b/ShimmerBluetooth/ShimmerBluetooth/IMUSensor.swift @@ -8,6 +8,11 @@ import Foundation public class IMUSensor: Sensor, IMUProcessing { + public let HardwareVersion: Int + required init(hwid: Int) { + self.HardwareVersion = hwid + super.init() + } public static func calibrateInertialSensorData(_ data: [Double], _ AM: [[Double]], _ SM: [[Double]], _ OV: [Double]) -> [Double]? { /* Based on the theory outlined by Ferraris F, Grimaldi U, and Parvis M. diff --git a/ShimmerBluetooth/ShimmerBluetooth/LNAccelSensor.swift b/ShimmerBluetooth/ShimmerBluetooth/LNAccelSensor.swift index b427f2a..edc94ed 100644 --- a/ShimmerBluetooth/ShimmerBluetooth/LNAccelSensor.swift +++ b/ShimmerBluetooth/ShimmerBluetooth/LNAccelSensor.swift @@ -8,6 +8,31 @@ import Foundation public class LNAccelSensor : IMUSensor , SensorProcessing{ + + public enum Range: UInt8 { + case RANGE_2G = 0x0 + case RANGE_4G = 0x1 + case RANGE_8G = 0x2 + case RANGE_16G = 0x3 + + public static func fromValue(_ value: UInt8) -> Range? { + switch value { + case 0: + return .RANGE_2G + case 1: + return .RANGE_4G + case 2: + return .RANGE_8G + case 3: + return .RANGE_16G + default: + return nil + } + } + + } + + var CurrentRange = Range.RANGE_2G public static let LOW_NOISE_ACCELEROMETER_X = "Low Noise Accelerometer X" public static let LOW_NOISE_ACCELEROMETER_Y = "Low Noise Accelerometer Y" public static let LOW_NOISE_ACCELEROMETER_Z = "Low Noise Accelerometer Z" @@ -17,23 +42,48 @@ public class LNAccelSensor : IMUSensor , SensorProcessing{ var AlignmentMatrix:[[Double]] = [[]] var SensitivityMatrix:[[Double]] = [[]] var OffsetVector:[Double]=[] - let CALIBRATION_ID = 2 + var CalibrationID = 2 + var AlignmentMatrix_2G:[[Double]] = [[]] + var SensitivityMatrix_2G:[[Double]] = [[]] + var OffsetVector_2G:[Double]=[] + var AlignmentMatrix_4G:[[Double]] = [[]] + var SensitivityMatrix_4G:[[Double]] = [[]] + var OffsetVector_4G:[Double]=[] + var AlignmentMatrix_8G:[[Double]] = [[]] + var SensitivityMatrix_8G:[[Double]] = [[]] + var OffsetVector_8G:[Double]=[] + var AlignmentMatrix_16G:[[Double]] = [[]] + var SensitivityMatrix_16G:[[Double]] = [[]] + var OffsetVector_16G:[Double]=[] + var lnAccelRange = 1 + + var calibBytes_2G: [UInt8] = [] + var calibBytes_4G: [UInt8] = [] + var calibBytes_8G: [UInt8] = [] + var calibBytes_16G: [UInt8] = [] public func processData(sensorPacket: [UInt8], objectCluster: ObjectCluster) -> ObjectCluster { let x = Array(sensorPacket[packetIndexAccelX.. [UInt8]{ + var infomemtoupdate = infomem + if(HardwareVersion == Shimmer3Protocol.HardwareType.Shimmer3R.rawValue){ + var lnAccelRange = 0 + var calibBytes = calibBytes_2G + if (range == Range.RANGE_2G){ + lnAccelRange = 0 + calibBytes = calibBytes_2G + } else if (range == Range.RANGE_4G){ + lnAccelRange = 1 + calibBytes = calibBytes_4G + } else if (range == Range.RANGE_8G){ + lnAccelRange = 2 + calibBytes = calibBytes_8G + } else if (range == Range.RANGE_16G){ + lnAccelRange = 3 + calibBytes = calibBytes_16G + } + + infomemtoupdate.replaceSubrange( + ConfigByteLayoutShimmer3.idxLSM6DSVAccelCalibration..Range{ + return CurrentRange } public func setInfoMem(infomem: [UInt8]) { @@ -62,6 +171,35 @@ public class LNAccelSensor : IMUSensor , SensorProcessing{ } else { sensorEnabled = false } + if(HardwareVersion == Shimmer3Protocol.HardwareType.Shimmer3R.rawValue){ + lnAccelRange = (Int(infomem[ConfigByteLayoutShimmer3.idxConfigSetupByte3]>>ConfigByteLayoutShimmer3.bitShiftMPU9150AccelRange) & ConfigByteLayoutShimmer3.maskMPU9150AccelRange) + if (lnAccelRange == 0){ + CurrentRange = Range.RANGE_2G + AlignmentMatrix = AlignmentMatrix_2G + SensitivityMatrix = SensitivityMatrix_2G + OffsetVector = OffsetVector_2G + } + if (lnAccelRange == 1){ + CurrentRange = Range.RANGE_4G + AlignmentMatrix = AlignmentMatrix_4G + SensitivityMatrix = SensitivityMatrix_4G + OffsetVector = OffsetVector_4G + } + if (lnAccelRange == 2){ + CurrentRange = Range.RANGE_8G + AlignmentMatrix = AlignmentMatrix_8G + SensitivityMatrix = SensitivityMatrix_8G + OffsetVector = OffsetVector_8G + } + if (lnAccelRange == 3){ + CurrentRange = Range.RANGE_16G + AlignmentMatrix = AlignmentMatrix_16G + SensitivityMatrix = SensitivityMatrix_16G + OffsetVector = OffsetVector_16G + } + } + + } diff --git a/ShimmerBluetooth/ShimmerBluetooth/MagSensor.swift b/ShimmerBluetooth/ShimmerBluetooth/MagSensor.swift index 520ac08..ea3ab28 100644 --- a/ShimmerBluetooth/ShimmerBluetooth/MagSensor.swift +++ b/ShimmerBluetooth/ShimmerBluetooth/MagSensor.swift @@ -8,6 +8,7 @@ import Foundation public class MagSensor : IMUSensor , SensorProcessing{ + public var packetIndexMagX:Int = -1 public var packetIndexMagY:Int = -1 public var packetIndexMagZ:Int = -1 @@ -15,11 +16,11 @@ public class MagSensor : IMUSensor , SensorProcessing{ public static let MAGNETOMETER_Y = "Magnetometer Y" public static let MAGNETOMETER_Z = "Magnetometer Z" var magRange = 0 - let CALIBRATION_ID = 32 + var CALIBRATION_ID = 32 var AlignmentMatrix : [[Double]] = [[]] var SensitivityMatrix : [[Double]] = [[]] var OffsetVector : [Double] = [] - + public func processData(sensorPacket: [UInt8], objectCluster: ObjectCluster) -> ObjectCluster { let x = Array(sensorPacket[packetIndexMagX..>5) & 1 + var enabled = Int(infomem[ConfigByteLayoutShimmer3.idxSensors0]>>ConfigByteLayoutShimmer3.bitShiftLSM303DLHCMagRange) & 1 if (enabled == 1){ sensorEnabled = true - } else { + } else { sensorEnabled = false } - - magRange = Int((infomem[8]>>5) & 7) - } - + public func setLowPowerMag(enable: Bool, isShimmer3withUpdatedSensors: Bool, isShimmer3Sensor: Bool, samplingRate: Double, infomem: [UInt8])-> [UInt8]{ let LowPowerMagEnabled = enable var infomemtoupdate = infomem - if(isShimmer3Sensor){ + if(HardwareVersion == Shimmer3Protocol.HardwareType.Shimmer3R.rawValue){ if(!LowPowerMagEnabled){ - if(isShimmer3withUpdatedSensors){ - if(samplingRate >= 100){ - infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:3) - }else if(samplingRate >= 50){ - infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:2) - }else if(samplingRate >= 20){ - infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:1) - }else if(samplingRate >= 10){ - infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:0) + if(samplingRate <= 10){ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:0) + }else if(samplingRate <= 20){ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:1) + }else if(samplingRate <= 50){ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:2) + }else{ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:3) + } + }else{ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:0) + } + }else { + if(isShimmer3Sensor){ + if(!LowPowerMagEnabled){ + if(isShimmer3withUpdatedSensors){ + if(samplingRate >= 100){ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:3) + }else if(samplingRate >= 50){ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:2) + }else if(samplingRate >= 20){ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:1) + }else if(samplingRate >= 10){ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:0) + }else{ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:0) + } }else{ + if(samplingRate >= 50){ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:6) + }else if(samplingRate >= 20){ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:5) + }else if(samplingRate >= 10){ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:4) + }else{ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:3) + } + } + }else //low power mag for shimmer3 enabled + { + if(isShimmer3withUpdatedSensors){ infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:0) + }else{ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:4) } - }else{ - if(samplingRate >= 50){ - infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:6) - }else if(samplingRate >= 20){ + } + }else //Shimmer2 + { + if(!LowPowerMagEnabled){ + if(samplingRate <= 1){ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:1) + }else if(samplingRate <= 15){ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:4) + }else if(samplingRate <= 30){ infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:5) - }else if(samplingRate >= 10){ + }else if(samplingRate <= 75){ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:6) + }else{ + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:7) + } + + }else + { + if(samplingRate >= 10){ infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:4) }else{ - infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:3) + infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:1) } } - }else //low power mag for shimmer3 enabled - { - if(isShimmer3withUpdatedSensors){ - infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:0) - }else{ - infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:4) - } - } - }else //Shimmer2 - { - if(!LowPowerMagEnabled){ - if(samplingRate <= 1){ - infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:1) - }else if(samplingRate <= 15){ - infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:4) - }else if(samplingRate <= 30){ - infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:5) - }else if(samplingRate <= 75){ - infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:6) - }else{ - infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:7) - } - - }else - { - if(samplingRate >= 10){ - infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:4) - }else{ - infomemtoupdate = updateInfoMemMagRate(infomem: infomem, magRate:1) - } } } + + + return infomemtoupdate } @@ -138,16 +158,14 @@ public class MagSensor : IMUSensor , SensorProcessing{ let orivalue = infomemtoupdate[ConfigByteLayoutShimmer3.idxConfigSetupByte2] let value = infomemtoupdate[ConfigByteLayoutShimmer3.idxConfigSetupByte2] & ~UInt8(ConfigByteLayoutShimmer3.maskLSM303DLHCMagSamplingRate< [UInt8]{ - var infomemtoupdate = infomem - print("oriinfomem: \(infomemtoupdate)") - - var pressReso = 0 - if (res == Resolution.RES_LOW){ - pressReso = 0 - } else if (res == Resolution.RES_STANDARD){ - pressReso = 1 - } else if (res == Resolution.RES_HIGH){ - pressReso = 2 - } else if (res == Resolution.RES_ULTRAHIGH){ - pressReso = 3 - } - let orivalue = infomemtoupdate[ConfigByteLayoutShimmer3.idxConfigSetupByte3] - let value = infomemtoupdate[ConfigByteLayoutShimmer3.idxConfigSetupByte3] & ~UInt8(ConfigByteLayoutShimmer3.maskBMPX80PressureResolution<= 6 { - signalDataTypeArray.append(SensorDataType.u24) packetSize = TimeStampPacketByteSize // Time stamp timeSensor.packetIndexTimeStamp = 0 timeSensor.sensorEnabled = true @@ -837,230 +872,131 @@ public class Shimmer3Protocol : NSObject, ShimmerProtocol { switch signalIdByte { case ChannelContentsShimmer3.XLNAccel.rawValue: - //if HardwareVersion == ShimmerVersion.SHIMMER3 { - signalNameArray.append(LNAccelSensor.LOW_NOISE_ACCELEROMETER_X) - signalDataTypeArray.append(SensorDataType.u12) lnAccelSensor.packetIndexAccelX = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_A_ACCEL.rawValue) - /*} else if HardwareVersion == ShimmerVersion.SHIMMER2R { - signalNameArray.append(Shimmer2Configuration.SignalNames.ACCELEROMETER_X) - signalDataTypeArray.append("u12") - packetSize += 2 - enabledSensors |= Int(SensorBitmapShimmer2.SENSOR_ACCEL) - }*/ case ChannelContentsShimmer3.YLNAccel.rawValue: - //if HardwareVersion == ShimmerVersion.SHIMMER3 { - signalNameArray.append(LNAccelSensor.LOW_NOISE_ACCELEROMETER_Y) - signalDataTypeArray.append(SensorDataType.u12) lnAccelSensor.packetIndexAccelY = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_A_ACCEL.rawValue) - /*} else if HardwareVersion == ShimmerVersion.SHIMMER2R { - signalNameArray.append(Shimmer2Configuration.SignalNames.ACCELEROMETER_Y) - signalDataTypeArray.append("u12") - packetSize += 2 - enabledSensors |= Int(SensorBitmapShimmer2.SENSOR_ACCEL) - }*/ case ChannelContentsShimmer3.ZLNAccel.rawValue: - //if HardwareVersion == ShimmerVersion.SHIMMER3 { - signalNameArray.append(LNAccelSensor.LOW_NOISE_ACCELEROMETER_Z) - signalDataTypeArray.append(SensorDataType.u12) lnAccelSensor.packetIndexAccelZ = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_A_ACCEL.rawValue) - /*} else if HardwareVersion == ShimmerVersion.SHIMMER2R { - signalNameArray.append(Shimmer2Configuration.SignalNames.ACCELEROMETER_Z) - signalDataTypeArray.append("u12") - packetSize += 2 - enabledSensors |= Int(SensorBitmapShimmer2.SENSOR_ACCEL) - }*/ case ChannelContentsShimmer3.VBatt.rawValue: - //if HardwareVersion == ShimmerVersion.SHIMMER3 { - signalNameArray.append(Shimmer3Configuration.SignalNames.V_SENSE_BATT) - signalDataTypeArray.append(SensorDataType.i16) packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_VBATT.rawValue) - /*} else if HardwareVersion == ShimmerVersion.SHIMMER2R { - signalNameArray.append(Shimmer2Configuration.SignalNames.GYROSCOPE_X) - signalDataTypeArray.append("u12") - packetSize += 2 - enabledSensors |= Int(SensorBitmapShimmer2.SENSOR_GYRO) - }*/ - // Add more cases for other signal IDs... case ChannelContentsShimmer3.XWRAccel.rawValue: - //if HardwareVersion == ShimmerVersion.SHIMMER3 { - signalNameArray.append(WRAccelSensor.WIDE_RANGE_ACCELEROMETER_X) - signalDataTypeArray.append(SensorDataType.i16) wrAccelSensor.packetIndexAccelX = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_D_ACCEL.rawValue) - case ChannelContentsShimmer3.YWRAccel.rawValue: - //if HardwareVersion == ShimmerVersion.SHIMMER3 { - signalNameArray.append(WRAccelSensor.WIDE_RANGE_ACCELEROMETER_Y) - signalDataTypeArray.append(SensorDataType.i16) wrAccelSensor.packetIndexAccelY = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_D_ACCEL.rawValue) - case ChannelContentsShimmer3.ZWRAccel.rawValue: - //if HardwareVersion == ShimmerVersion.SHIMMER3 { - signalNameArray.append(WRAccelSensor.WIDE_RANGE_ACCELEROMETER_Z) - signalDataTypeArray.append(SensorDataType.i16) wrAccelSensor.packetIndexAccelZ = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_D_ACCEL.rawValue) case ChannelContentsShimmer3.XMag.rawValue: - //if HardwareVersion == ShimmerVersion.SHIMMER3 { - signalNameArray.append(Shimmer3Configuration.SignalNames.MAGNETOMETER_X) - signalDataTypeArray.append(SensorDataType.i16) magSensor.packetIndexMagX = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_LSM303DLHC_MAG.rawValue) - case ChannelContentsShimmer3.YMag.rawValue: - //if HardwareVersion == ShimmerVersion.SHIMMER3 { - signalNameArray.append(Shimmer3Configuration.SignalNames.MAGNETOMETER_Y) - signalDataTypeArray.append(SensorDataType.i16) magSensor.packetIndexMagY = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_LSM303DLHC_MAG.rawValue) - case ChannelContentsShimmer3.ZMag.rawValue: - //if HardwareVersion == ShimmerVersion.SHIMMER3 { - signalNameArray.append(Shimmer3Configuration.SignalNames.MAGNETOMETER_Z) - signalDataTypeArray.append(SensorDataType.i16) magSensor.packetIndexMagZ = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_LSM303DLHC_MAG.rawValue) + case ChannelContentsShimmer3.AlternativeXMag.rawValue: //AlternativeXMag + altMagSensor.packetIndexAltMagX = packetSize + packetSize += 2 + enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_LIS3MDL_ALT_MAG.rawValue) + case ChannelContentsShimmer3.AlternativeYMag.rawValue: + altMagSensor.packetIndexAltMagY = packetSize + packetSize += 2 + enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_LIS3MDL_ALT_MAG.rawValue) + case ChannelContentsShimmer3.AlternativeZMag.rawValue: + altMagSensor.packetIndexAltMagZ = packetSize + packetSize += 2 + enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_LIS3MDL_ALT_MAG.rawValue) case ChannelContentsShimmer3.XGyro.rawValue: - //if HardwareVersion == ShimmerVersion.SHIMMER3 { - signalNameArray.append(GyroSensor.GYROSCOPE_X) - signalDataTypeArray.append(SensorDataType.i16MSB) gyroSensor.packetIndexGyroX = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_MPU9150_GYRO.rawValue) - case ChannelContentsShimmer3.YGyro.rawValue: - //if HardwareVersion == ShimmerVersion.SHIMMER3 { - signalNameArray.append(GyroSensor.GYROSCOPE_Y) - signalDataTypeArray.append(SensorDataType.i16MSB) gyroSensor.packetIndexGyroY = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_MPU9150_GYRO.rawValue) - case ChannelContentsShimmer3.ZGyro.rawValue: - //if HardwareVersion == ShimmerVersion.SHIMMER3 { - signalNameArray.append(GyroSensor.GYROSCOPE_Z) - signalDataTypeArray.append(SensorDataType.i16MSB) gyroSensor.packetIndexGyroZ = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_MPU9150_GYRO.rawValue) case ChannelContentsShimmer3.GsrRaw.rawValue: - signalNameArray.append(GSRSensor.GSR) - signalDataTypeArray.append(SensorDataType.u16) gsrSensor.packetIndex = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_GSR.rawValue) case ChannelContentsShimmer3.Exg1_Status.rawValue: - signalNameArray.append(Shimmer3Configuration.SignalNames.EXG1_STATUS) - signalDataTypeArray.append(SensorDataType.u8) packetSize += 1 case ChannelContentsShimmer3.Exg1_CH1.rawValue: - signalNameArray.append(Shimmer3Configuration.SignalNames.EXG1_CH1_24BIT) - signalDataTypeArray.append(SensorDataType.i24MSB) packetSize += 3 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_EXG1_24BIT.rawValue) case ChannelContentsShimmer3.Exg1_CH2.rawValue: - signalNameArray.append(Shimmer3Configuration.SignalNames.EXG1_CH2_24BIT) - signalDataTypeArray.append(SensorDataType.i24MSB) packetSize += 3 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_EXG1_24BIT.rawValue) case ChannelContentsShimmer3.Exg2_Status.rawValue: - signalNameArray.append(Shimmer3Configuration.SignalNames.EXG2_STATUS) - signalDataTypeArray.append(SensorDataType.u8) packetSize += 1 case ChannelContentsShimmer3.Exg2_CH1.rawValue: - signalNameArray.append(Shimmer3Configuration.SignalNames.EXG2_CH1_24BIT) - signalDataTypeArray.append(SensorDataType.i24MSB) packetSize += 3 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_EXG2_24BIT.rawValue) case ChannelContentsShimmer3.Exg2_CH2.rawValue: - signalNameArray.append(Shimmer3Configuration.SignalNames.EXG2_CH2_24BIT) - signalDataTypeArray.append(SensorDataType.i24MSB) packetSize += 3 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_EXG2_24BIT.rawValue) case ChannelContentsShimmer3.Exg1_CH1_16Bit.rawValue: - signalNameArray.append(Shimmer3Configuration.SignalNames.EXG1_CH1_16BIT) - signalDataTypeArray.append(SensorDataType.i16MSB) packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_EXG1_16BIT.rawValue) case ChannelContentsShimmer3.Exg1_CH2_16Bit.rawValue: - signalNameArray.append(Shimmer3Configuration.SignalNames.EXG1_CH2_16BIT) - signalDataTypeArray.append(SensorDataType.i16MSB) packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_EXG1_16BIT.rawValue) case ChannelContentsShimmer3.Exg2_CH1_16Bit.rawValue: - signalNameArray.append(Shimmer3Configuration.SignalNames.EXG2_CH1_16BIT) - signalDataTypeArray.append(SensorDataType.i16MSB) packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_EXG2_16BIT.rawValue) case ChannelContentsShimmer3.Exg2_CH2_16Bit.rawValue: - signalNameArray.append(Shimmer3Configuration.SignalNames.EXG2_CH2_16BIT) - signalDataTypeArray.append(SensorDataType.i16MSB) packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_EXG2_16BIT.rawValue) case ChannelContentsShimmer3.InternalAdc13.rawValue: - signalNameArray.append(ADCSensor.ADCType.Shimmer3_A13.description) - signalDataTypeArray.append(SensorDataType.u12) adcA13Sensor.packetIndex = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_INT_A13.rawValue) case ChannelContentsShimmer3.ExternalAdc15.rawValue: - signalNameArray.append(ADCSensor.ADCType.Shimmer3_A15.description) - signalDataTypeArray.append(SensorDataType.u12) adcA15Sensor.packetIndex = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_EXT_A15.rawValue) case ChannelContentsShimmer3.InternalAdc12.rawValue: - signalNameArray.append(ADCSensor.ADCType.Shimmer3_A12.description) - signalDataTypeArray.append(SensorDataType.u12) adcA12Sensor.packetIndex = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_INT_A12.rawValue) case ChannelContentsShimmer3.InternalAdc1.rawValue: - signalNameArray.append(ADCSensor.ADCType.Shimmer3_A1.description) - signalDataTypeArray.append(SensorDataType.u12) adcA1Sensor.packetIndex = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_INT_A1.rawValue) case ChannelContentsShimmer3.ExternalAdc6.rawValue: - signalNameArray.append(ADCSensor.ADCType.Shimmer3_A6.description) - signalDataTypeArray.append(SensorDataType.u12) adcA6Sensor.packetIndex = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_EXT_A6.rawValue) case ChannelContentsShimmer3.ExternalAdc7.rawValue: - signalNameArray.append(ADCSensor.ADCType.Shimmer3_A7.description) - signalDataTypeArray.append(SensorDataType.u12) adcA7Sensor.packetIndex = packetSize packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_EXT_A7.rawValue) case ChannelContentsShimmer3.Temperature.rawValue: - signalNameArray.append(Shimmer3Configuration.SignalNames.TEMPERATURE) - signalDataTypeArray.append(SensorDataType.u16MSB) packetSize += 2 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_BMP180_PRESSURE.rawValue) case ChannelContentsShimmer3.Pressure.rawValue: - signalNameArray.append(Shimmer3Configuration.SignalNames.PRESSURE) - signalDataTypeArray.append(SensorDataType.u24MSB) packetSize += 3 enabledSensors |= Int(SensorBitmapShimmer3.SENSOR_BMP180_PRESSURE.rawValue) - default: - signalNameArray.append("") - signalDataTypeArray.append(SensorDataType.u12) packetSize += 2 } @@ -1068,12 +1004,7 @@ public class Shimmer3Protocol : NSObject, ShimmerProtocol { } EnabledSensors = enabledSensors - SignalNameArray = signalNameArray - SignalDataTypeArray = signalDataTypeArray PacketSize = packetSize + Int(CRCMode.rawValue) - - print(SignalNameArray) - print(SignalDataTypeArray) print(PacketSize) //print("Packet Size : \(PacketSize) CRC Mode and starting byte not included") } @@ -1130,6 +1061,53 @@ public class Shimmer3Protocol : NSObject, ShimmerProtocol { } } + func interpretInquiryResponseShimmer3R(packet: [UInt8]) { + // Check if this packet is sane and not just random + if packet.count >= 4 { // Max number of channels currently allowable + let ADCRawSamplingRateValue = Int(packet[0]) + (Int(packet[1]) << 8 & 0xFF00) + CurrentSamplingRate = Double(32768) / Double(ADCRawSamplingRateValue) + + let ConfigSetupByte0 = Int64(packet[2]) + (Int64(packet[3]) << 8) + (Int64(packet[4]) << 16) + (Int64(packet[5]) << 24) + let AccelHRBit = Int((ConfigSetupByte0 >> 0) & 0x01) + let AccelLPBit = Int((ConfigSetupByte0 >> 1) & 0x01) + let AccelRange = Int((ConfigSetupByte0 >> 2) & 0x03) + let GyroRange = Int((ConfigSetupByte0 >> 16) & 0x03) + let MagGain = Int((ConfigSetupByte0 >> 21) & 0x07) + let AccelSamplingRate = Int((ConfigSetupByte0 >> 4) & 0xF) + let Mpu9150SamplingRate = Int((ConfigSetupByte0 >> 8) & 0xFF) + let magSamplingRate = Int((ConfigSetupByte0 >> 18) & 0x07) + let PressureResolution = Int((ConfigSetupByte0 >> 28) & 0x03) + let GSRRange = Int((ConfigSetupByte0 >> 25) & 0x07) + let InternalExpPower = Int((ConfigSetupByte0 >> 24) & 0x01) + let Mpu9150AccelRange = Int((ConfigSetupByte0 >> 30) & 0x03) + + if magSamplingRate == 4 && ADCRawSamplingRateValue < 3200 { + // 3200 is the raw ADC value and not in HZ + let LowPowerMagEnabled = true + } + + if AccelSamplingRate == 2 && ADCRawSamplingRateValue < 3200 { + let LowPowerAccelEnabled = true + } + + if Mpu9150SamplingRate == 0xFF && ADCRawSamplingRateValue < 3200 { + let LowPowerGyroEnabled = true + } + + let NumberofChannels = Int(packet[6+3]) + let BufferSize = Int(packet[7+3]) + var ListofSensorChannels: [UInt8] = [] + + for i in 0.. Bool?{ + private func sendBMP280PressureCalibCoefficientsCommand() async -> Bool?{ let bytes:[UInt8] = [PacketTypeShimmer.getBmp280CalibrationCoefficientsCommand.rawValue] commandSent = PacketTypeShimmer.getBmp280CalibrationCoefficientsCommand @@ -1298,6 +1276,10 @@ public class Shimmer3Protocol : NSObject, ShimmerProtocol { } } + private func sendPressureCalibCoefficientsCommand() async -> Bool?{ + return true; + } + public func sendSetSamplingRateCommand(samplingRate: Double) async -> Bool?{ var samplingByteValue = (Int)(32768/samplingRate) var bytes = [UInt8]() @@ -1644,6 +1626,7 @@ public class Shimmer3Protocol : NSObject, ShimmerProtocol { case SENSOR_EXG1_16BIT = 0x100000 case SENSOR_EXG2_16BIT = 0x080000 case SENSOR_BRIDGE_AMP = 0x8000 + case SENSOR_LIS3MDL_ALT_MAG = 0x200000 } enum ChannelContentsShimmer3: UInt8 { @@ -1762,6 +1745,8 @@ public class Shimmer3Protocol : NSObject, ShimmerProtocol { case bmp180CalibrationCoefficientsResponse = 0x58 case getBmp280CalibrationCoefficientsCommand = 0xA0 case bmp280CalibrationCoefficientsResponse = 0x9F + case getpressureCalibrationCoefficientsCommand = 0xA7 + case pressureCalibrationCoefficientsResponse = 0xA6 case setExgRegsCommand = 0x61 case exgRegsResponse = 0x62 case getExgRegsCommand = 0x63 diff --git a/ShimmerBluetooth/ShimmerBluetooth/WRAccelSensor.swift b/ShimmerBluetooth/ShimmerBluetooth/WRAccelSensor.swift index 2237678..26e5273 100644 --- a/ShimmerBluetooth/ShimmerBluetooth/WRAccelSensor.swift +++ b/ShimmerBluetooth/ShimmerBluetooth/WRAccelSensor.swift @@ -41,7 +41,7 @@ public class WRAccelSensor : IMUSensor , SensorProcessing{ public static let WIDE_RANGE_ACCELEROMETER_Y = "Wide Range Accelerometer Y" public static let WIDE_RANGE_ACCELEROMETER_Z = "Wide Range Accelerometer Z" - let CALIBRATION_ID = 31 + var CalibrationID = 31 var AlignmentMatrix_2G:[[Double]] = [[]] var SensitivityMatrix_2G:[[Double]] = [[]] var OffsetVector_2G:[Double]=[] @@ -59,6 +59,12 @@ public class WRAccelSensor : IMUSensor , SensorProcessing{ var SensitivityMatrix : [[Double]] = [[]] var OffsetVector : [Double] = [] + var calibBytes_2G: [UInt8] = [] + var calibBytes_4G: [UInt8] = [] + var calibBytes_8G: [UInt8] = [] + var calibBytes_16G: [UInt8] = [] + + public func processData(sensorPacket: [UInt8], objectCluster: ObjectCluster) -> ObjectCluster { let x = Array(sensorPacket[packetIndexAccelX.. [UInt8]{ var infomemtoupdate = infomem var wrAccelRange = 0 - if (range == Range.RANGE_2G){ - wrAccelRange = 0 - } else if (range == Range.RANGE_4G){ - wrAccelRange = 2 - } else if (range == Range.RANGE_8G){ - wrAccelRange = 3 - } else if (range == Range.RANGE_16G){ - wrAccelRange = 1 + var calibBytes = calibBytes_2G + if(HardwareVersion == Shimmer3Protocol.HardwareType.Shimmer3.rawValue){ + if (range == Range.RANGE_2G){ + wrAccelRange = 0 + calibBytes = calibBytes_2G + } else if (range == Range.RANGE_4G){ + wrAccelRange = 2 + calibBytes = calibBytes_4G + } else if (range == Range.RANGE_8G){ + wrAccelRange = 3 + calibBytes = calibBytes_8G + } else if (range == Range.RANGE_16G){ + wrAccelRange = 1 + calibBytes = calibBytes_16G + } + }else if(HardwareVersion == Shimmer3Protocol.HardwareType.Shimmer3R.rawValue){ + if (range == Range.RANGE_2G){ + wrAccelRange = 0 + calibBytes = calibBytes_2G + } else if (range == Range.RANGE_4G){ + wrAccelRange = 1 + calibBytes = calibBytes_4G + } else if (range == Range.RANGE_8G){ + wrAccelRange = 2 + calibBytes = calibBytes_8G + } else if (range == Range.RANGE_16G){ + wrAccelRange = 3 + calibBytes = calibBytes_16G + } } - let orivalue = infomemtoupdate[ConfigByteLayoutShimmer3.idxConfigSetupByte0] - let value = infomemtoupdate[ConfigByteLayoutShimmer3.idxConfigSetupByte0] & ~UInt8(ConfigByteLayoutShimmer3.maskLSM303DLHCAccelRange<Range{ @@ -138,31 +199,58 @@ public class WRAccelSensor : IMUSensor , SensorProcessing{ } wrAccelRange = (Int(infomem[ConfigByteLayoutShimmer3.idxConfigSetupByte0]>>ConfigByteLayoutShimmer3.bitShiftLSM303DLHCAccelRange) & ConfigByteLayoutShimmer3.maskLSM303DLHCAccelRange) - if (wrAccelRange == 0){ - CurrentRange = Range.RANGE_2G - AlignmentMatrix = AlignmentMatrix_2G - SensitivityMatrix = SensitivityMatrix_2G - OffsetVector = OffsetVector_2G - } - if (wrAccelRange == 2){ - CurrentRange = Range.RANGE_4G - AlignmentMatrix = AlignmentMatrix_4G - SensitivityMatrix = SensitivityMatrix_4G - OffsetVector = OffsetVector_4G - } - if (wrAccelRange == 3){ - CurrentRange = Range.RANGE_8G - AlignmentMatrix = AlignmentMatrix_8G - SensitivityMatrix = SensitivityMatrix_8G - OffsetVector = OffsetVector_8G - } - if (wrAccelRange == 1){ - CurrentRange = Range.RANGE_16G - AlignmentMatrix = AlignmentMatrix_16G - SensitivityMatrix = SensitivityMatrix_16G - OffsetVector = OffsetVector_16G + + if(HardwareVersion == Shimmer3Protocol.HardwareType.Shimmer3.rawValue){ + if (wrAccelRange == 0){ + CurrentRange = Range.RANGE_2G + AlignmentMatrix = AlignmentMatrix_2G + SensitivityMatrix = SensitivityMatrix_2G + OffsetVector = OffsetVector_2G + } + if (wrAccelRange == 2){ + CurrentRange = Range.RANGE_4G + AlignmentMatrix = AlignmentMatrix_4G + SensitivityMatrix = SensitivityMatrix_4G + OffsetVector = OffsetVector_4G + } + if (wrAccelRange == 3){ + CurrentRange = Range.RANGE_8G + AlignmentMatrix = AlignmentMatrix_8G + SensitivityMatrix = SensitivityMatrix_8G + OffsetVector = OffsetVector_8G + } + if (wrAccelRange == 1){ + CurrentRange = Range.RANGE_16G + AlignmentMatrix = AlignmentMatrix_16G + SensitivityMatrix = SensitivityMatrix_16G + OffsetVector = OffsetVector_16G + } + }else if(HardwareVersion == Shimmer3Protocol.HardwareType.Shimmer3R.rawValue){ + if (wrAccelRange == 0){ + CurrentRange = Range.RANGE_2G + AlignmentMatrix = AlignmentMatrix_2G + SensitivityMatrix = SensitivityMatrix_2G + OffsetVector = OffsetVector_2G + } + if (wrAccelRange == 1){ + CurrentRange = Range.RANGE_4G + AlignmentMatrix = AlignmentMatrix_4G + SensitivityMatrix = SensitivityMatrix_4G + OffsetVector = OffsetVector_4G + } + if (wrAccelRange == 2){ + CurrentRange = Range.RANGE_8G + AlignmentMatrix = AlignmentMatrix_8G + SensitivityMatrix = SensitivityMatrix_8G + OffsetVector = OffsetVector_8G + } + if (wrAccelRange == 3){ + CurrentRange = Range.RANGE_16G + AlignmentMatrix = AlignmentMatrix_16G + SensitivityMatrix = SensitivityMatrix_16G + OffsetVector = OffsetVector_16G + } } - } public func setLowPowerWRAccel(enable: Bool, isShimmer3withUpdatedSensors: Bool, samplingRate: Double, infomem: [UInt8])-> [UInt8]{ diff --git a/ShimmerBluetooth/ShimmerBluetoothTests/SensorTest.swift b/ShimmerBluetooth/ShimmerBluetoothTests/SensorTest.swift index 059ebdc..4846cf6 100644 --- a/ShimmerBluetooth/ShimmerBluetoothTests/SensorTest.swift +++ b/ShimmerBluetooth/ShimmerBluetoothTests/SensorTest.swift @@ -13,11 +13,17 @@ import CoreBluetooth class SensorTest: XCTestCase { func testSensorWRAccel(){ - var wrAccelSensor: WRAccelSensor = WRAccelSensor() + var wrAccelSensor: WRAccelSensor = WRAccelSensor(hwid: Shimmer3Protocol.HardwareType.Shimmer3.rawValue) var infomwracc:[UInt8] = [ 0x80,0x02,0x01,0xE0,0x20,0x00,0x01,0x9B,0x0D,0x08,0x00,0x80,0x10,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x00,0x80,0x10,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x09,0x00,0x00,0x00,0x08,0xCD,0x08,0xCD,0x08,0xCD,0x00,0x5C,0x00,0x5C,0x00,0x5C,0x00,0x9C,0x00,0x9C,0x00,0x00,0x00,0x00,0x9C,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x96,0x19,0x96,0x19,0x96,0x00,0x9C,0x00,0x9C,0x00,0x00,0x00,0x00,0x9C,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x9B,0x02,0x9B,0x02,0x9B,0x00,0x9C,0x00,0x64,0x00,0x00,0x00,0x00,0x9C,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x87,0x06,0x87,0x06,0x87,0x00,0x9C,0x00,0x64,0x00,0x00,0x00,0x00,0x9C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x68,0x69,0x6D,0x6D,0x65,0x72,0x5F,0x36,0x38,0x44,0x44,0x44,0x65,0x66,0x61,0x75,0x6C,0x74,0x54,0x72,0x69,0x61,0x6C,0x65,0x54,0x7E,0x40,0x00,0x00,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ] + //parse calib bytes for all accel ranges + wrAccelSensor.parseSensorCalibrationDump(bytes: [0x1F, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x87, 0x06, 0x87, 0x06, 0x87, 0x00, 0x9C, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x9C]) + wrAccelSensor.parseSensorCalibrationDump(bytes: [0x1F, 0x00, 0x01, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0x00, 0xD1, 0x00, 0xD1, 0x00, 0x9C, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x9C]) + wrAccelSensor.parseSensorCalibrationDump(bytes: [0x1F, 0x00, 0x02, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x44, 0x03, 0x44, 0x03, 0x44, 0x00, 0x9C, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x9C]) + wrAccelSensor.parseSensorCalibrationDump(bytes: [0x1F, 0x00, 0x03, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA2, 0x01, 0xA2, 0x01, 0xA2, 0x00, 0x9C, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x9C]) + infomwracc = wrAccelSensor.updateInfoMemAccelRange(infomem: infomwracc,range: WRAccelSensor.Range.RANGE_16G) var wrAccelRange = (Int(infomwracc[ConfigByteLayoutShimmer3.idxConfigSetupByte0]>>ConfigByteLayoutShimmer3.bitShiftLSM303DLHCAccelRange) & ConfigByteLayoutShimmer3.maskLSM303DLHCAccelRange) XCTAssertEqual(wrAccelRange, 1, "Failed to set accel range") @@ -37,11 +43,17 @@ class SensorTest: XCTestCase { } func testSensorGyroRange(){ - var gyroSensor: GyroSensor = GyroSensor() + var gyroSensor: GyroSensor = GyroSensor(hwid: Shimmer3Protocol.HardwareType.Shimmer3.rawValue) var infomgyro:[UInt8] = [ 0x20, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x06, 0x01, 0x08, 0x04, 0x88, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x04, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x0B, 0x00, 0x00, 0x00, 0x08, 0xCD, 0x08, 0xCD, 0x08, 0xCD, 0x00, 0x5C, 0x00, 0x5C, 0x00, 0x5C, 0x00, 0x9C, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x96, 0x19, 0x96, 0x19, 0x96, 0x00, 0x9C, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x9B, 0x02, 0x9B, 0x02, 0x9B, 0x00, 0x9C, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x87, 0x06, 0x87, 0x06, 0x87, 0x00, 0x9C, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x68, 0x69, 0x6D, 0x6D, 0x65, 0x72, 0x5F, 0x36, 0x38, 0x44, 0x44, 0x74, 0x72, 0x74, 0x72, 0x74, 0x72, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x4C, 0x45, 0xA6, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x47, 0x8F, 0x04, 0xBD, 0xA2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ] + //parse calib bytes for all gyro ranges + gyroSensor.parseSensorCalibrationDump(bytes: [0x1E, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x2C, 0x33, 0x2C, 0x33, 0x2C, 0x00, 0x9C, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x9C]) + gyroSensor.parseSensorCalibrationDump(bytes: [0x1E, 0x00, 0x01, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x96, 0x19, 0x96, 0x19, 0x96, 0x00, 0x9C, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x9C]) + gyroSensor.parseSensorCalibrationDump(bytes: [0x1E, 0x00, 0x02, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xD0, 0x0C, 0xD0, 0x0C, 0xD0, 0x00, 0x9C, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x9C]) + gyroSensor.parseSensorCalibrationDump(bytes: [0x1E, 0x00, 0x03, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x68, 0x06, 0x68, 0x06, 0x68, 0x00, 0x9C, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x9C]) + infomgyro = gyroSensor.updateInfoMemGyroRange(infomem: infomgyro,range: GyroSensor.Range.RANGE_250DPS) var gyroRange = (Int(infomgyro[ConfigByteLayoutShimmer3.idxConfigSetupByte2] >> ConfigByteLayoutShimmer3.bitShiftMPU9150GyroRange) & ConfigByteLayoutShimmer3.maskMPU9150GyroRange) @@ -60,7 +72,7 @@ class SensorTest: XCTestCase { XCTAssertEqual(gyroRange, 3, "Failed to set gyro range") } func testSensorPressureResolution(){ - var pressTempSensor: PressureTempSensor = PressureTempSensor() + var pressTempSensor: PressureTempSensor = PressureTempSensor(hwid: Shimmer3Protocol.HardwareType.Shimmer3.rawValue) var infompressuretemp:[UInt8] = [0x80, 0x02, 0x01, 0x00, 0x00, 0x04, 0x01, 0xFF, 0x01, 0x08, 0x00, 0x88, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x09, 0x00, 0x00, 0x00, 0x08, 0xCD, 0x08, 0xCD, 0x08, 0xCD, 0x00, 0x5C, 0x00, 0x5C, 0x00, 0x5C, 0x00, 0x9C, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x96, 0x19, 0x96, 0x19, 0x96, 0x00, 0x9C, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x9B, 0x02, 0x9B, 0x02, 0x9B, 0x00, 0x9C, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x87, 0x06, 0x87, 0x06, 0x87, 0x00, 0x9C, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x68, 0x69, 0x6D, 0x6D, 0x65, 0x72, 0x5F, 0x36, 0x38, 0x44, 0x44, 0x74, 0x72, 0x74, 0x72, 0x74, 0x72, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x65, 0xD4, 0xBD, 0x5F, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0xEB, 0x1B, 0x97, 0x67, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/ShimmerExamplePlot/ShimmerExamplePlot/ContentView.swift b/ShimmerExamplePlot/ShimmerExamplePlot/ContentView.swift index 89df7d2..0da8f55 100644 --- a/ShimmerExamplePlot/ShimmerExamplePlot/ContentView.swift +++ b/ShimmerExamplePlot/ShimmerExamplePlot/ContentView.swift @@ -7,6 +7,7 @@ import SwiftUI import Charts +import ShimmerBluetooth struct ToyShape: Identifiable { var type: String @@ -61,7 +62,7 @@ struct ContentView: View { @State private var rangeSelection = 0 @State private var protocolSelection = 0 @State private var deviceSelection = 0 - + var body: some View { ScrollView { Picker(selection: $selectionS, label: Text("Number Of Signals (Max 3)")) { @@ -134,7 +135,7 @@ struct ContentView: View { print(protocolSelection) viewModel.protocolShimmer3 = protocolSelection } - + Text("BT State: \(viewModel.stateText)") Button("Connect Shimmer3",action: {Task { do { @@ -155,162 +156,250 @@ struct ContentView: View { } }) - Button("StartStreaming Shimmer3",action:{ Task { - do { - await viewModel.sendStartStreamingCommandDev2() - } catch { - print("Error: \(error)") - } - } - }) - Button("StopStreaming Shimmer3",action:{ Task { - do { - await viewModel.sendStopStreamingCommandDev2() - } catch { - print("Error: \(error)") - } - } - }) - Button("WriteInfoMem WRAccel Shimmer3",action:{ Task { - do { - await viewModel.sendInfoMemAccel() - } catch { - print("Error: \(error)") - } - } - }) - Button("WriteInfoMem IMU Shimmer3",action:{ Task { - do { - await viewModel.sendInfoMemIMU() - } catch { - print("Error: \(error)") + Button("StartStreaming Shimmer3",action:{ Task { + do { + await viewModel.sendStartStreamingCommandDev2() + } catch { + print("Error: \(error)") + } } - } - }) - Button("WriteInfoMem PPG+GSR Shimmer3",action:{ Task { - do { - await viewModel.sendInfoMemPPGGSR() - } catch { - print("Error: \(error)") + }) + Button("StopStreaming Shimmer3",action:{ Task { + do { + await viewModel.sendStopStreamingCommandDev2() + } catch { + print("Error: \(error)") + } } - } - }) + }) + if (viewModel.shimmer3Protocol?.REV_HW_MAJOR==Shimmer3Protocol.HardwareType.Shimmer3.rawValue){ + Button("WriteInfoMem WRAccel Shimmer3",action:{ Task { + do { + await viewModel.sendInfoMemWRAccel() + } catch { + print("Error: \(error)") + } + } + }) + Button("WriteInfoMem IMU Shimmer3",action:{ Task { + do { + await viewModel.sendInfoMemIMU() + } catch { + print("Error: \(error)") + } + } + }) + Button("WriteInfoMem Pressure Temperature Shimmer3",action:{ Task { + do { + await viewModel.sendInfoMemPressureAndTemperature() + } catch { + print("Error: \(error)") + } + } + }) + Button("WriteInfoMem PPG+GSR Shimmer3",action:{ Task { + do { + await viewModel.sendInfoMemPPGGSR() + } catch { + print("Error: \(error)") + } + } + }) + + Button("WriteInfoMem ECG 24-bit Shimmer3",action:{ Task { + do { + await viewModel.sendInfoMemECG24Bit() + } catch { + print("Error: \(error)") + } + } + }) + Button("WriteInfoMem ECG 16-bit Shimmer3",action:{ Task { + do { + await viewModel.sendInfoMemECG16Bit() + } catch { + print("Error: \(error)") + } + } + }) + Button("WriteInfoMem EMG Shimmer3",action:{ Task { + do { + await viewModel.sendInfoMemEMG() + } catch { + print("Error: \(error)") + } + } + }) + Button("WriteInfoMem EXG Test Shimmer3",action:{ Task { + do { + await viewModel.sendInfoMemEXGTest() + } catch { + print("Error: \(error)") + } + } + }) + Button("WriteInfoMem Respiration Shimmer3",action:{ Task { + do { + await viewModel.sendInfoMemRespiration() + } catch { + print("Error: \(error)") + } + } + }) + Button("WriteInfoMem Battery Voltage Shimmer3",action:{ Task { + do { + await viewModel.sendInfoMemBattery() + } catch { + print("Error: \(error)") + } + } + }) + } else if (viewModel.shimmer3Protocol?.REV_HW_MAJOR==Shimmer3Protocol.HardwareType.Shimmer3R.rawValue){ + Button("WriteInfoMem LNAccel Shimmer3R",action:{ Task { + do { + await viewModel.sendInfoMemS3RLNAccel() + } catch { + print("Error: \(error)") + } + } + }) - Button("WriteInfoMem ECG 24-bit Shimmer3",action:{ Task { - do { - await viewModel.sendInfoMemECG24Bit() - } catch { - print("Error: \(error)") + Button("WriteInfoMem Alt Mag Shimmer3R",action:{ Task { + do { + await viewModel.sendInfoMemS3RAltMag() + } catch { + print("Error: \(error)") + } + } + }) + + Button("WriteInfoMem Mag Shimmer3R",action:{ Task { + do { + await viewModel.sendInfoMemS3RMag() + } catch { + print("Error: \(error)") + } + } + }) + + Button("WriteInfoMem Gyro Shimmer3R",action:{ Task { + do { + await viewModel.sendInfoMemS3RGyro() + } catch { + print("Error: \(error)") + } + } + }) + + Button("WriteInfoMem WRAccel Shimmer3R",action:{ Task { + do { + await viewModel.sendInfoMemS3RWRAccel() + } catch { + print("Error: \(error)") + } + } + }) } - } - }) - Button("WriteInfoMem ECG 16-bit Shimmer3",action:{ Task { - do { - await viewModel.sendInfoMemECG16Bit() - } catch { - print("Error: \(error)") + Picker("Select EXG Gain", selection: $viewModel.exgGainIndex) { + ForEach(0..=1){ - if (message.SignalData.count0){ - self.signal1.append(message.SignalData[startIndex+0]) + + if (message.SignalData.count >= 1) { + if (message.SignalData.count < self.startIndex + self.numberOfSignals) { + self.startIndex = 0 + } + if (self.numberOfSignals > 0) { + self.signal1.append(message.SignalData[self.startIndex + 0]) + } } - } - if (message.SignalData.count>=2){ - if (numberOfSignals>1){ - self.signal2.append(message.SignalData[startIndex+1]) + if (message.SignalData.count >= 2) { + if (self.numberOfSignals > 1) { + self.signal2.append(message.SignalData[self.startIndex + 1]) + } } - } - if (message.SignalData.count>=3){ - if (numberOfSignals>2){ - self.signal3.append(message.SignalData[startIndex+2]) + if (message.SignalData.count >= 3) { + if (self.numberOfSignals > 2) { + self.signal3.append(message.SignalData[self.startIndex + 2]) + } + } + if (self.signal1.count == 500) { + self.signal1.removeFirst() + } + if (self.signal2.count == 500) { + self.signal2.removeFirst() + } + if (self.signal3.count == 500) { + self.signal3.removeFirst() + } + self.count += 1 + if (self.count % 10 == 0) { + self.delegate?.plotEvent(message: "") } - } - if (signal1.count==500){ - signal1.removeFirst() - } - if (signal2.count==500){ - signal2.removeFirst() - } - if (signal3.count==500){ - signal3.removeFirst() - } - self.count+=1 - if (self.count%10 == 0){ - self.delegate?.plotEvent(message: "") } }