github.com/SkycoinProject/gomobile@v0.0.0-20190312151609-d3739f865fa6/exp/sensor/darwin_armx.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build darwin 6 // +build arm arm64 7 8 package sensor 9 10 /* 11 #cgo CFLAGS: -x objective-c 12 #cgo LDFLAGS: -framework CoreMotion 13 14 #import <stdlib.h> 15 16 void GoIOS_createManager(); 17 18 void GoIOS_startAccelerometer(float interval); 19 void GoIOS_stopAccelerometer(); 20 void GoIOS_readAccelerometer(int64_t* timestamp, float* vector); 21 22 void GoIOS_startGyro(float interval); 23 void GoIOS_stopGyro(); 24 void GoIOS_readGyro(int64_t* timestamp, float* vector); 25 26 void GoIOS_startMagneto(float interval); 27 void GoIOS_stopMagneto(); 28 void GoIOS_readMagneto(int64_t* timestamp, float* vector); 29 30 void GoIOS_destroyManager(); 31 */ 32 import "C" 33 import ( 34 "fmt" 35 "sync" 36 "time" 37 "unsafe" 38 ) 39 40 var channels struct { 41 sync.Mutex 42 done [nTypes]chan struct{} 43 } 44 45 func init() { 46 C.GoIOS_createManager() 47 } 48 49 // minDelay is the minimum delay allowed. 50 // 51 // From Event Handling Guide for iOS: 52 // 53 // "You can set the reporting interval to be as small as 10 54 // milliseconds (ms), which corresponds to a 100 Hz update rate, 55 // but most app operate sufficiently with a larger interval." 56 // 57 // There is no need to poll more frequently than once every 10ms. 58 // 59 // https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/motion_event_basics/motion_event_basics.html 60 61 const minDelay = 10 * time.Millisecond 62 63 // enable enables the sensor t on sender. A non-nil sender is 64 // required before calling enable. 65 func enable(t Type, delay time.Duration) error { 66 channels.Lock() 67 defer channels.Unlock() 68 69 if channels.done[t] != nil { 70 return fmt.Errorf("sensor: cannot enable; %v sensor is already enabled", t) 71 } 72 channels.done[t] = make(chan struct{}) 73 74 if delay < minDelay { 75 delay = minDelay 76 } 77 interval := C.float(float64(delay) / float64(time.Second)) 78 79 switch t { 80 case Accelerometer: 81 C.GoIOS_startAccelerometer(interval) 82 case Gyroscope: 83 C.GoIOS_startGyro(interval) 84 case Magnetometer: 85 C.GoIOS_startMagneto(interval) 86 } 87 go pollSensor(t, delay, channels.done[t]) 88 return nil 89 } 90 91 func disable(t Type) error { 92 channels.Lock() 93 defer channels.Unlock() 94 95 if channels.done[t] == nil { 96 return fmt.Errorf("sensor: cannot disable; %v sensor is not enabled", t) 97 } 98 close(channels.done[t]) 99 channels.done[t] = nil 100 101 switch t { 102 case Accelerometer: 103 C.GoIOS_stopAccelerometer() 104 case Gyroscope: 105 C.GoIOS_stopGyro() 106 case Magnetometer: 107 C.GoIOS_stopMagneto() 108 } 109 return nil 110 } 111 112 func pollSensor(t Type, d time.Duration, done chan struct{}) { 113 var lastTimestamp int64 114 115 var timestamp C.int64_t 116 var ev [3]C.float 117 118 for { 119 select { 120 case <-done: 121 return 122 default: 123 tp := (*C.int64_t)(unsafe.Pointer(×tamp)) 124 vp := (*C.float)(unsafe.Pointer(&ev[0])) 125 126 switch t { 127 case Accelerometer: 128 C.GoIOS_readAccelerometer(tp, vp) 129 case Gyroscope: 130 C.GoIOS_readGyro(tp, vp) 131 case Magnetometer: 132 C.GoIOS_readMagneto(tp, vp) 133 } 134 ts := int64(timestamp) 135 if ts > lastTimestamp { 136 // TODO(jbd): Do we need to convert the values to another unit? 137 // How does iOS units compare to the Android units. 138 sender.Send(Event{ 139 Sensor: t, 140 Timestamp: ts, 141 Data: []float64{float64(ev[0]), float64(ev[1]), float64(ev[2])}, 142 }) 143 lastTimestamp = ts 144 time.Sleep(d / 2) 145 } 146 } 147 } 148 } 149 150 // TODO(jbd): Remove destroy? 151 func destroy() error { 152 C.GoIOS_destroyManager() 153 return nil 154 }