exp/sensor: support gyro events on darwin{arm,arm64}
Change-Id: I47aa12cc942261b8035312d0eeba0caf52b562ac
Reviewed-on: https://go-review.googlesource.com/14257
Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/exp/sensor/darwin_armx.go b/exp/sensor/darwin_armx.go
index ac93737..612882e 100644
--- a/exp/sensor/darwin_armx.go
+++ b/exp/sensor/darwin_armx.go
@@ -19,6 +19,10 @@
void GoIOS_stopAccelerometer();
void GoIOS_readAccelerometer(int64_t* timestamp, float* vector);
+void GoIOS_startGyro(float interval);
+void GoIOS_stopGyro();
+void GoIOS_readGyro(int64_t* timestamp, float* vector);
+
void GoIOS_destroyManager();
*/
import "C"
@@ -31,7 +35,7 @@
var channels struct {
sync.Mutex
- acceleroDone chan struct{}
+ done [nTypes]chan struct{}
}
type manager struct {
@@ -59,25 +63,26 @@
channels.Lock()
defer channels.Unlock()
+ if channels.done[t] != nil {
+ return fmt.Errorf("sensor: cannot enable; %v sensor is already enabled", t)
+ }
+ channels.done[t] = make(chan struct{})
+
if delay < minDelay {
delay = minDelay
}
+ interval := float64(delay) / float64(time.Second)
switch t {
case Accelerometer:
- if channels.acceleroDone != nil {
- return fmt.Errorf("sensor: cannot enable; %v sensor is already enabled", t)
- }
- // TODO(jbd): Check if accelerometer is available.
- interval := float64(delay) / float64(time.Second)
C.GoIOS_startAccelerometer(C.float(interval))
- channels.acceleroDone = make(chan struct{})
- go m.runAccelerometer(s, delay, channels.acceleroDone)
case Gyroscope:
+ C.GoIOS_startGyro(C.float(interval))
case Magnetometer:
- default:
- return fmt.Errorf("sensor: unknown sensor type: %v", t)
+ return fmt.Errorf("sensor: %v is not supported yet", t)
}
+
+ go m.pollSensor(s, t, delay, channels.done[t])
return nil
}
@@ -85,15 +90,17 @@
channels.Lock()
defer channels.Unlock()
+ if channels.done[t] == nil {
+ return fmt.Errorf("sensor: cannot disable; %v sensor is not enabled", t)
+ }
+ close(channels.done[t])
+ channels.done[t] = nil
+
switch t {
case Accelerometer:
- if channels.acceleroDone == nil {
- return fmt.Errorf("sensor: cannot disable; %v sensor is not enabled", t)
- }
- close(channels.acceleroDone)
- channels.acceleroDone = nil
C.GoIOS_stopAccelerometer()
case Gyroscope:
+ C.GoIOS_stopGyro()
case Magnetometer:
default:
return fmt.Errorf("sensor: unknown sensor type: %v", t)
@@ -101,26 +108,33 @@
return nil
}
-func (m *manager) runAccelerometer(s Sender, d time.Duration, done chan struct{}) {
+func (m *manager) pollSensor(s Sender, t Type, d time.Duration, done chan struct{}) {
+ var lastTimestamp int64
+
var timestamp C.int64_t
var ev [3]C.float
- var lastTimestamp int64
+
for {
select {
case <-done:
return
default:
- C.GoIOS_readAccelerometer((*C.int64_t)(unsafe.Pointer(×tamp)), (*C.float)(unsafe.Pointer(&ev[0])))
- t := int64(timestamp)
- if t > lastTimestamp {
+ switch t {
+ case Accelerometer:
+ C.GoIOS_readAccelerometer((*C.int64_t)(unsafe.Pointer(×tamp)), (*C.float)(unsafe.Pointer(&ev[0])))
+ case Gyroscope:
+ C.GoIOS_readGyro((*C.int64_t)(unsafe.Pointer(×tamp)), (*C.float)(unsafe.Pointer(&ev[0])))
+ }
+ ts := int64(timestamp)
+ if ts > lastTimestamp {
// TODO(jbd): Do we need to convert the values to another unit?
// How does iOS units compare to the Android units.
s.Send(Event{
- Sensor: Accelerometer,
- Timestamp: t,
+ Sensor: t,
+ Timestamp: ts,
Data: []float64{float64(ev[0]), float64(ev[1]), float64(ev[2])},
})
- lastTimestamp = t
+ lastTimestamp = ts
time.Sleep(d / 2)
}
}
diff --git a/exp/sensor/darwin_armx.m b/exp/sensor/darwin_armx.m
index 654e6ae..a775a46 100644
--- a/exp/sensor/darwin_armx.m
+++ b/exp/sensor/darwin_armx.m
@@ -30,6 +30,23 @@
v[2] = data.acceleration.z;
}
+void GoIOS_startGyro(float interval) {
+ manager.gyroUpdateInterval = interval;
+ [manager startGyroUpdates];
+}
+
+void GoIOS_stopGyro() {
+ [manager stopGyroUpdates];
+}
+
+void GoIOS_readGyro(int64_t* timestamp, float* v) {
+ CMGyroData* data = manager.gyroData;
+ *timestamp = (int64_t)(data.timestamp * 1000 * 1000);
+ v[0] = data.rotationRate.x;
+ v[1] = data.rotationRate.y;
+ v[2] = data.rotationRate.z;
+}
+
void GoIOS_destroyManager() {
[manager release];
manager = nil;
diff --git a/exp/sensor/sensor.go b/exp/sensor/sensor.go
index 90ec7ed..eea4e83 100644
--- a/exp/sensor/sensor.go
+++ b/exp/sensor/sensor.go
@@ -31,6 +31,7 @@
Accelerometer = Type(0)
Gyroscope = Type(1)
Magnetometer = Type(2)
+ nTypes = Type(3)
)
// Event represents a sensor event.