mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-26 10:38:41 +00:00
936a255df9
* Add support for CEVA BNO08x 9DoF sensor. Also includes implementation of CEVA SH-2 and SHTP protocols.
* Replace machine.I2C with drivers.I2C interface to remove dependency on machine package
* Replace Pin functionality with that provided by tinygo.org/x/drivers/internal/pin
* Unexport fields on SensorValue and replace with accessor methods. Add check for correct SensorID validation
* Add example to smoketest.sh
* Change build target for smoketest to match development environment.. Probably not important, but matches reality.
* Fix decoding of some sensor data: Step Counter, Tap Detector, Flip Detector. These are experimental.
* Refactor to allow SPI/UART etc. SPI is currently under development, but is omitted from this commit.
Example code has been moved to i2c subdirectory.
This commit introduces some major refactoring changes. It introduces a "Buser" interface and tries to remove any I2C specific code from the core. It still retains a couple of I2C specific fields in the "Config" struct ("Address" and "ReadChunk") but they are ignored in the as yet uncommited SPI code.
* Fix CRLF -> LF for gofmt
* Update smoketest to point to new example file
317 lines
7.8 KiB
Go
317 lines
7.8 KiB
Go
package bno08x
|
|
|
|
import "encoding/binary"
|
|
|
|
// decodeSensor decodes a sensor report payload into a SensorValue.
|
|
func decodeSensor(payload []byte, timestamp uint32) (SensorValue, bool) {
|
|
if len(payload) < 4 {
|
|
return SensorValue{}, false
|
|
}
|
|
|
|
value := SensorValue{
|
|
id: SensorID(payload[0]),
|
|
sequence: payload[1],
|
|
status: payload[2] & 0x03,
|
|
delay: payload[3],
|
|
timestamp: uint64(timestamp),
|
|
}
|
|
|
|
data := payload[4:]
|
|
|
|
switch value.id {
|
|
case SensorRawAccelerometer:
|
|
if len(data) >= 10 {
|
|
value.rawAccelerometer = RawVector3{
|
|
X: int16(binary.LittleEndian.Uint16(data[0:])),
|
|
Y: int16(binary.LittleEndian.Uint16(data[2:])),
|
|
Z: int16(binary.LittleEndian.Uint16(data[4:])),
|
|
Timestamp: binary.LittleEndian.Uint32(data[6:]),
|
|
}
|
|
}
|
|
|
|
case SensorAccelerometer:
|
|
if len(data) >= 6 {
|
|
value.accelerometer = Vector3{
|
|
X: qToFloat(data[0:], scaleAccel),
|
|
Y: qToFloat(data[2:], scaleAccel),
|
|
Z: qToFloat(data[4:], scaleAccel),
|
|
}
|
|
}
|
|
|
|
case SensorLinearAcceleration:
|
|
if len(data) >= 6 {
|
|
value.linearAcceleration = Vector3{
|
|
X: qToFloat(data[0:], scaleAccel),
|
|
Y: qToFloat(data[2:], scaleAccel),
|
|
Z: qToFloat(data[4:], scaleAccel),
|
|
}
|
|
}
|
|
|
|
case SensorGravity:
|
|
if len(data) >= 6 {
|
|
value.gravity = Vector3{
|
|
X: qToFloat(data[0:], scaleAccel),
|
|
Y: qToFloat(data[2:], scaleAccel),
|
|
Z: qToFloat(data[4:], scaleAccel),
|
|
}
|
|
}
|
|
|
|
case SensorRawGyroscope:
|
|
if len(data) >= 12 {
|
|
value.rawGyroscope = RawGyroscope{
|
|
X: int16(binary.LittleEndian.Uint16(data[0:])),
|
|
Y: int16(binary.LittleEndian.Uint16(data[2:])),
|
|
Z: int16(binary.LittleEndian.Uint16(data[4:])),
|
|
Temperature: int16(binary.LittleEndian.Uint16(data[6:])),
|
|
Timestamp: binary.LittleEndian.Uint32(data[8:]),
|
|
}
|
|
}
|
|
|
|
case SensorGyroscope:
|
|
if len(data) >= 6 {
|
|
value.gyroscope = Vector3{
|
|
X: qToFloat(data[0:], scaleGyro),
|
|
Y: qToFloat(data[2:], scaleGyro),
|
|
Z: qToFloat(data[4:], scaleGyro),
|
|
}
|
|
}
|
|
|
|
case SensorGyroscopeUncalibrated:
|
|
if len(data) >= 12 {
|
|
value.gyroscopeUncal = GyroscopeUncalibrated{
|
|
X: qToFloat(data[0:], scaleGyro),
|
|
Y: qToFloat(data[2:], scaleGyro),
|
|
Z: qToFloat(data[4:], scaleGyro),
|
|
BiasX: qToFloat(data[6:], scaleGyro),
|
|
BiasY: qToFloat(data[8:], scaleGyro),
|
|
BiasZ: qToFloat(data[10:], scaleGyro),
|
|
}
|
|
}
|
|
|
|
case SensorRawMagnetometer:
|
|
if len(data) >= 10 {
|
|
value.rawMagnetometer = RawVector3{
|
|
X: int16(binary.LittleEndian.Uint16(data[0:])),
|
|
Y: int16(binary.LittleEndian.Uint16(data[2:])),
|
|
Z: int16(binary.LittleEndian.Uint16(data[4:])),
|
|
Timestamp: binary.LittleEndian.Uint32(data[6:]),
|
|
}
|
|
}
|
|
|
|
case SensorMagneticField:
|
|
if len(data) >= 6 {
|
|
value.magneticField = Vector3{
|
|
X: qToFloat(data[0:], scaleMag),
|
|
Y: qToFloat(data[2:], scaleMag),
|
|
Z: qToFloat(data[4:], scaleMag),
|
|
}
|
|
}
|
|
|
|
case SensorMagneticFieldUncalibrated:
|
|
if len(data) >= 12 {
|
|
value.magneticFieldUncal = MagneticFieldUncalibrated{
|
|
X: qToFloat(data[0:], scaleMag),
|
|
Y: qToFloat(data[2:], scaleMag),
|
|
Z: qToFloat(data[4:], scaleMag),
|
|
BiasX: qToFloat(data[6:], scaleMag),
|
|
BiasY: qToFloat(data[8:], scaleMag),
|
|
BiasZ: qToFloat(data[10:], scaleMag),
|
|
}
|
|
}
|
|
|
|
case SensorRotationVector:
|
|
if len(data) >= 10 {
|
|
value.quaternion = Quaternion{
|
|
I: qToFloat(data[0:], scaleQuat),
|
|
J: qToFloat(data[2:], scaleQuat),
|
|
K: qToFloat(data[4:], scaleQuat),
|
|
Real: qToFloat(data[6:], scaleQuat),
|
|
}
|
|
value.quaternionAccuracy = qToFloat(data[8:], scaleAccuracy)
|
|
}
|
|
|
|
case SensorGameRotationVector:
|
|
if len(data) >= 8 {
|
|
value.quaternion = Quaternion{
|
|
I: qToFloat(data[0:], scaleQuat),
|
|
J: qToFloat(data[2:], scaleQuat),
|
|
K: qToFloat(data[4:], scaleQuat),
|
|
Real: qToFloat(data[6:], scaleQuat),
|
|
}
|
|
}
|
|
|
|
case SensorGeomagneticRotationVector:
|
|
if len(data) >= 10 {
|
|
value.quaternion = Quaternion{
|
|
I: qToFloat(data[0:], scaleQuat),
|
|
J: qToFloat(data[2:], scaleQuat),
|
|
K: qToFloat(data[4:], scaleQuat),
|
|
Real: qToFloat(data[6:], scaleQuat),
|
|
}
|
|
value.quaternionAccuracy = qToFloat(data[8:], scaleAccuracy)
|
|
}
|
|
|
|
case SensorARVRStabilizedRV:
|
|
if len(data) >= 10 {
|
|
value.quaternion = Quaternion{
|
|
I: qToFloat(data[0:], scaleQuat),
|
|
J: qToFloat(data[2:], scaleQuat),
|
|
K: qToFloat(data[4:], scaleQuat),
|
|
Real: qToFloat(data[6:], scaleQuat),
|
|
}
|
|
value.quaternionAccuracy = qToFloat(data[8:], scaleAccuracy)
|
|
}
|
|
|
|
case SensorARVRStabilizedGRV:
|
|
if len(data) >= 8 {
|
|
value.quaternion = Quaternion{
|
|
I: qToFloat(data[0:], scaleQuat),
|
|
J: qToFloat(data[2:], scaleQuat),
|
|
K: qToFloat(data[4:], scaleQuat),
|
|
Real: qToFloat(data[6:], scaleQuat),
|
|
}
|
|
}
|
|
|
|
case SensorGyroIntegratedRV:
|
|
if len(data) >= 10 {
|
|
value.quaternion = Quaternion{
|
|
I: qToFloat(data[0:], scaleQuat),
|
|
J: qToFloat(data[2:], scaleQuat),
|
|
K: qToFloat(data[4:], scaleQuat),
|
|
Real: qToFloat(data[6:], scaleQuat),
|
|
}
|
|
// Angular velocity X at data[8:10]
|
|
}
|
|
|
|
case SensorPressure:
|
|
if len(data) >= 4 {
|
|
value.pressure = float32(int32(binary.LittleEndian.Uint32(data[0:]))) * scalePressure
|
|
}
|
|
|
|
case SensorAmbientLight:
|
|
if len(data) >= 4 {
|
|
value.ambientLight = float32(int32(binary.LittleEndian.Uint32(data[0:]))) * scaleLight
|
|
}
|
|
|
|
case SensorHumidity:
|
|
if len(data) >= 2 {
|
|
value.humidity = qToFloat(data[0:], scaleHumidity)
|
|
}
|
|
|
|
case SensorProximity:
|
|
if len(data) >= 2 {
|
|
value.proximity = qToFloat(data[0:], scaleProximity)
|
|
}
|
|
|
|
case SensorTemperature:
|
|
if len(data) >= 2 {
|
|
value.temperature = qToFloat(data[0:], scaleTemperature)
|
|
}
|
|
|
|
case SensorTapDetector:
|
|
if len(data) >= 1 {
|
|
value.tapDetector = TapDetector{
|
|
Flags: data[0],
|
|
}
|
|
}
|
|
|
|
case SensorStepDetector:
|
|
if len(data) >= 4 {
|
|
value.stepDetector = StepDetector{
|
|
Latency: binary.LittleEndian.Uint32(data[0:]),
|
|
}
|
|
}
|
|
|
|
case SensorStepCounter:
|
|
if len(data) >= 8 {
|
|
value.stepCounter = StepCounter{
|
|
Count: uint16(binary.LittleEndian.Uint32(data[4:8])),
|
|
Latency: binary.LittleEndian.Uint32(data[0:4]),
|
|
}
|
|
}
|
|
|
|
case SensorSignificantMotion:
|
|
if len(data) >= 2 {
|
|
value.significantMotion = SignificantMotion{
|
|
Motion: binary.LittleEndian.Uint16(data[0:]),
|
|
}
|
|
}
|
|
|
|
case SensorStabilityClassifier:
|
|
if len(data) >= 1 {
|
|
value.stabilityClassifier = StabilityClassifier{
|
|
Classification: data[0],
|
|
}
|
|
}
|
|
|
|
case SensorStabilityDetector:
|
|
if len(data) >= 1 {
|
|
value.stabilityDetector = data[0]
|
|
}
|
|
|
|
case SensorShakeDetector:
|
|
if len(data) >= 2 {
|
|
value.shakeDetector = ShakeDetector{
|
|
Shake: binary.LittleEndian.Uint16(data[0:]),
|
|
}
|
|
}
|
|
|
|
case SensorFlipDetector:
|
|
if len(data) >= 2 {
|
|
value.flipDetector = binary.LittleEndian.Uint16(data[0:2])
|
|
}
|
|
|
|
case SensorPickupDetector:
|
|
if len(data) >= 2 {
|
|
// Pickup detected at data[0:2]
|
|
}
|
|
|
|
case SensorPersonalActivityClassifier:
|
|
if len(data) >= 16 {
|
|
value.personalActivityClassifier = PersonalActivityClassifier{
|
|
Page: data[0],
|
|
MostLikelyState: data[1],
|
|
EndOfPage: data[15],
|
|
}
|
|
for i := 0; i < 10 && i+2 < len(data); i++ {
|
|
value.personalActivityClassifier.Confidence[i] = data[2+i]
|
|
}
|
|
}
|
|
|
|
case SensorSleepDetector:
|
|
if len(data) >= 1 {
|
|
value.sleepDetector = data[0]
|
|
}
|
|
|
|
case SensorTiltDetector:
|
|
if len(data) >= 1 {
|
|
value.tiltDetector = data[0]
|
|
}
|
|
|
|
case SensorPocketDetector:
|
|
if len(data) >= 1 {
|
|
value.pocketDetector = data[0]
|
|
}
|
|
|
|
case SensorCircleDetector:
|
|
if len(data) >= 1 {
|
|
value.circleDetector = data[0]
|
|
}
|
|
|
|
case SensorHeartRateMonitor:
|
|
if len(data) >= 2 {
|
|
value.heartRateMonitor = binary.LittleEndian.Uint16(data[0:])
|
|
}
|
|
}
|
|
|
|
return value, true
|
|
}
|
|
|
|
// qToFloat converts a Q-point fixed-point value to float32.
|
|
func qToFloat(data []byte, scale float32) float32 {
|
|
if len(data) < 2 {
|
|
return 0
|
|
}
|
|
return float32(int16(binary.LittleEndian.Uint16(data))) * scale
|
|
}
|