exp/sensor: initiate the darwin/{arm,arm64} backend

The CL provides accelerometer events only, upcoming CLs will add
support for gyroscope and magnetometer.

Change-Id: Ib5629ca7c49c9dfc8ca533fe7acde371efc102b2
Reviewed-on: https://go-review.googlesource.com/14036
Reviewed-by: Nigel Tao <nigeltao@golang.org>
This commit is contained in:
Burcu Dogan 2015-08-31 22:49:57 -07:00
parent 9e2ad8c60e
commit 5651add1eb
2 changed files with 128 additions and 9 deletions

View File

@ -7,29 +7,113 @@
package sensor package sensor
/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework CoreMotion
#import <stdlib.h>
void GoIOS_createManager();
void GoIOS_startAccelerometer();
void GoIOS_stopAccelerometer();
void GoIOS_readAccelerometer(int64_t* timestamp, float* vector);
void GoIOS_destroyManager();
*/
import "C"
import ( import (
"errors" "fmt"
"sync"
"time" "time"
"unsafe"
) )
var channels struct {
sync.Mutex
acceleroDone chan struct{}
}
type manager struct { type manager struct {
} }
func (m *manager) initialize() { func (m *manager) initialize() {
C.GoIOS_createManager()
} }
func (m *manager) enable(s Sender, t Type, delay time.Duration) error { func (m *manager) enable(s Sender, t Type, delay time.Duration) error {
return errors.New("sensor: no sensors available") // TODO(jbd): If delay is smaller than 10 milliseconds, set it to
// 10 milliseconds. It is highest frequency iOS SDK suppports and
// we don't want to have time.Tick durations smaller than this value.
channels.Lock()
defer channels.Unlock()
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.
C.GoIOS_startAccelerometer()
channels.acceleroDone = make(chan struct{})
go m.runAccelerometer(s, delay, channels.acceleroDone)
case Gyroscope:
case Magnetometer:
default:
return fmt.Errorf("sensor: unknown sensor type: %v", t)
}
return nil
} }
func (m *manager) disable(t Type) error { func (m *manager) disable(t Type) error {
return errors.New("sensor: no sensors available") channels.Lock()
} defer channels.Unlock()
func (m *manager) read(e []Event) (n int, err error) { switch t {
return 0, errors.New("sensor: no sensor data available") case Accelerometer:
} if channels.acceleroDone == nil {
return fmt.Errorf("sensor: cannot disable; %v sensor is not enabled", t)
func (m *manager) close() error { }
close(channels.acceleroDone)
channels.acceleroDone = nil
C.GoIOS_stopAccelerometer()
case Gyroscope:
case Magnetometer:
default:
return fmt.Errorf("sensor: unknown sensor type: %v", t)
}
return nil
}
func (m *manager) runAccelerometer(s Sender, d time.Duration, done chan struct{}) {
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(&timestamp)), (*C.float)(unsafe.Pointer(&ev[0])))
t := int64(timestamp)
if t > 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,
Data: []float64{float64(ev[0]), float64(ev[1]), float64(ev[2])},
})
lastTimestamp = t
time.Sleep(d / 2)
}
}
}
}
// TODO(jbd): Remove close?
func (m *manager) close() error {
C.GoIOS_destroyManager()
return nil return nil
} }

35
exp/sensor/darwin_armx.m Normal file
View File

@ -0,0 +1,35 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin
// +build arm arm64
#import <CoreMotion/CoreMotion.h>
CMMotionManager* manager = nil;
void GoIOS_createManager() {
manager = [[CMMotionManager alloc] init];
}
void GoIOS_startAccelerometer() {
[manager startAccelerometerUpdates];
}
void GoIOS_stopAccelerometer() {
[manager stopAccelerometerUpdates];
}
void GoIOS_readAccelerometer(int64_t* timestamp, float* v) {
CMAccelerometerData* data = manager.accelerometerData;
*timestamp = (int64_t)(data.timestamp * 1000 * 1000);
v[0] = data.acceleration.x;
v[1] = data.acceleration.y;
v[2] = data.acceleration.z;
}
void GoIOS_destroyManager() {
[manager release];
manager = nil;
}