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