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:
parent
9e2ad8c60e
commit
5651add1eb
|
@ -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(×tamp)), (*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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue