Reputation: 55
I write an app for iOS using the TI SensorTag2. Right now i'm stuck with the conversion of data i read over bluetooth to Float for the app.
Following Code is from the released source code of TI for an Objective C App.
-(NSString *) calcValue:(NSData *) value {
char vals[value.length];
[value getBytes:vals length:value.length];
Point3D gyroPoint;
gyroPoint.x = ((float)((int16_t)((vals[0] & 0xff) | (((int16_t)vals[1] << 8) & 0xff00)))/ (float) 32768) * 255 * 1;
gyroPoint.y = ((float)((int16_t)((vals[2] & 0xff) | (((int16_t)vals[3] << 8) & 0xff00)))/ (float) 32768) * 255 * 1;
gyroPoint.z = ((float)((int16_t)((vals[4] & 0xff) | (((int16_t)vals[5] << 8) & 0xff00)))/ (float) 32768) * 255 * 1;
self.gyro = gyroPoint;
Point3D accPoint;
accPoint.x = (((float)((int16_t)((vals[6] & 0xff) | (((int16_t)vals[7] << 8) & 0xff00)))/ (float) 32768) * 8) * 1;
accPoint.y = (((float)((int16_t)((vals[8] & 0xff) | (((int16_t)vals[9] << 8) & 0xff00))) / (float) 32768) * 8) * 1;
accPoint.z = (((float)((int16_t)((vals[10] & 0xff) | (((int16_t)vals[11] << 8) & 0xff00)))/ (float) 32768) * 8) * 1;
self.acc = accPoint;
Point3D magPoint;
magPoint.x = (((float)((int16_t)((vals[12] & 0xff) | (((int16_t)vals[13] << 8) & 0xff00))) / (float) 32768) * 4912);
magPoint.y = (((float)((int16_t)((vals[14] & 0xff) | (((int16_t)vals[15] << 8) & 0xff00))) / (float) 32768) * 4912);
magPoint.z = (((float)((int16_t)((vals[16] & 0xff) | (((int16_t)vals[17] << 8) & 0xff00))) / (float) 32768) * 4912);
self.mag = magPoint;
return [NSString stringWithFormat:@"ACC : X: %+6.1f, Y: %+6.1f, Z: %+6.1f\nMAG : X: %+6.1f, Y: %+6.1f, Z: %+6.1f\nGYR : X: %+6.1f, Y: %+6.1f, Z: %+6.1f",self.acc.x,self.acc.y,self.acc.z,self.mag.x,self.mag.y,self.mag.z,self.gyro.x,self.gyro.y,self.gyro.z];
}
When i try to convert this code to Swift, i get an error "Integer literal '65280' overflows when stored into Int16
let xF: Float = ((Float((Int16(bytes[6]) & 0xff) | ((Int16(bytes[7]) << 8) & 0xff00)) / Float(32768)) * 8) * 1
As i understand that, it combines the 2 Int8 variables into a single Int16 and it should work, i just don't find where i made the error. The part with "& 0xff00" is marked and when i understand it right this is here so only the first 8 bits contain 1's , the rest is 0's
I had it working with code from the android app for SensorTag2, but that code crashes the app from time to time, when i do also read data from gyroscope, so i wanted to use that iOS Code
let x = (Int16(bytes[7]) << 8) + Int16(bytes[6])
let xF = Float(x) / (32768.0 / 8.0)
Maybe somebody here can point me in the right direction to solve my problem
Upvotes: 0
Views: 168
Reputation: 55
I couldn't use the UInt solution, because i get the data as raw bytes that are encoded as signed int with 16bit. In ObjectiveC they are read into a char-array, that i converted to Int8
But i found another solution and now i just read the bytes into a Int16 array, that way two following bytes will be treated as a single Int16, like the ObjectiveC code made them already.
var bytes: [Int16] = [Int16](count: data.length, repeatedValue: 0)
let dataLength = data.length
data.getBytes(&bytes, length: dataLength * sizeof(Int16))
That way i don't need the bitshifting and bit operations.
now i have an array of 9 Int16 values, instead of 16 Int8, that i had to convert to Int16. Also a test with the TI SensorTag App resulted in the same numbers
Upvotes: 0
Reputation: 47876
One bad thing in this line:
let xF: Float = ((Float((Int16(bytes[6]) & 0xff) | ((Int16(bytes[7]) << 8) & 0xff00)) / Float(32768)) * 8) * 1
is this: ((Int16(bytes[7]) << 8) & 0xff00)
.
You know Int16
can represent numbers -32768...32767, and the value of 0xff00 is 65280. As the error message is saying, it is too large for Int16
.
(Remember Swift does no implicit conversions for numeric types.)
With making bytes
as unsigned:
let bytes = UnsafePointer<UInt8>(data.bytes)
You have no need to use &
.
But you need to pass a signed value to Float.init
, so your code needs to be something like this:
let xF: Float = ((Float(Int16(bitPattern: UInt16(bytes[6]) | (UInt16(bytes[7]) << 8))) / Float(32768)) * 8) * 1
(Or else, negative values in bytes
make your app crash.)
Upvotes: 1