• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stdlib.h>
18 #include <string.h>
19 #include <float.h>
20 
21 #include <eventnums.h>
22 #include <gpio.h>
23 #include <heap.h>
24 #include <hostIntf.h>
25 #include <isr.h>
26 #include <nanohubPacket.h>
27 #include <sensors.h>
28 #include <seos.h>
29 #include <slab.h>
30 #include <timer.h>
31 #include <plat/gpio.h>
32 #include <plat/exti.h>
33 #include <plat/syscfg.h>
34 #include <variant/variant.h>
35 
36 #define VSYNC_APP_ID      APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 7)
37 #define VSYNC_APP_VERSION 2
38 
39 // This defines how many vsync events we could handle being backed up in the
40 // queue. Use this to size our slab
41 #define MAX_VSYNC_EVENTS        4
42 #define MAX_VSYNC_INT_LATENCY   1000 /* in ns */
43 
44 #ifndef VSYNC_PIN
45 #error "VSYNC_PIN is not defined; please define in variant.h"
46 #endif
47 
48 #ifndef VSYNC_IRQ
49 #error "VSYNC_IRQ is not defined; please define in variant.h"
50 #endif
51 
52 #define VERBOSE_PRINT(fmt, ...) do { \
53         osLog(LOG_VERBOSE, "%s " fmt, "[VSYNC]", ##__VA_ARGS__); \
54     } while (0);
55 
56 #define INFO_PRINT(fmt, ...) do { \
57         osLog(LOG_INFO, "%s " fmt, "[VSYNC]", ##__VA_ARGS__); \
58     } while (0);
59 
60 #define ERROR_PRINT(fmt, ...) INFO_PRINT("%s" fmt, "ERROR: ", ##__VA_ARGS__); \
61 
62 #define DEBUG_PRINT(fmt, ...) do { \
63         if (enable_debug) {  \
64             INFO_PRINT(fmt, ##__VA_ARGS__); \
65         } \
66     } while (0);
67 
68 static const bool __attribute__((unused)) enable_debug = 0;
69 
70 static struct SensorTask
71 {
72     struct Gpio *pin;
73     struct ChainedIsr isr;
74     struct SlabAllocator *evtSlab;
75 
76 
77     uint32_t id;
78     uint32_t sensorHandle;
79 
80     bool on;
81 } mTask;
82 
vsyncAllocateEvt(struct SingleAxisDataEvent ** evPtr,uint64_t time)83 static bool vsyncAllocateEvt(struct SingleAxisDataEvent **evPtr, uint64_t time)
84 {
85     struct SingleAxisDataEvent *ev;
86 
87     *evPtr = slabAllocatorAlloc(mTask.evtSlab);
88 
89     ev = *evPtr;
90     if (!ev) {
91         ERROR_PRINT("slabAllocatorAlloc() failed\n");
92         return false;
93     }
94 
95     memset(&ev->samples[0].firstSample, 0x00, sizeof(struct SensorFirstSample));
96     ev->referenceTime = time;
97     ev->samples[0].firstSample.numSamples = 1;
98     ev->samples[0].idata = 1;
99 
100     return true;
101 }
102 
vsyncFreeEvt(void * ptr)103 static void vsyncFreeEvt(void *ptr)
104 {
105     slabAllocatorFree(mTask.evtSlab, ptr);
106 }
107 
vsyncIsr(struct ChainedIsr * localIsr)108 static bool vsyncIsr(struct ChainedIsr *localIsr)
109 {
110     struct SensorTask *data = container_of(localIsr, struct SensorTask, isr);
111     struct SingleAxisDataEvent *ev;
112 
113     if (!extiIsPendingGpio(data->pin)) {
114         return false;
115     }
116 
117     if (data->on) {
118         if (vsyncAllocateEvt(&ev, sensorGetTime())) {
119             if (!osEnqueueEvtOrFree(sensorGetMyEventType(SENS_TYPE_VSYNC), ev, vsyncFreeEvt)) {
120                 ERROR_PRINT("osEnqueueEvtOrFree() failed\n");
121             }
122         }
123     }
124 
125     extiClearPendingGpio(data->pin);
126     return true;
127 }
128 
enableInterrupt(struct Gpio * pin,struct ChainedIsr * isr)129 static bool enableInterrupt(struct Gpio *pin, struct ChainedIsr *isr)
130 {
131     gpioConfigInput(pin, GPIO_SPEED_LOW, GPIO_PULL_NONE);
132     syscfgSetExtiPort(pin);
133     extiEnableIntGpio(pin, EXTI_TRIGGER_FALLING);
134     extiChainIsr(VSYNC_IRQ, isr);
135     return true;
136 }
137 
disableInterrupt(struct Gpio * pin,struct ChainedIsr * isr)138 static bool disableInterrupt(struct Gpio *pin, struct ChainedIsr *isr)
139 {
140     extiUnchainIsr(VSYNC_IRQ, isr);
141     extiDisableIntGpio(pin);
142     return true;
143 }
144 
145 static const struct SensorInfo mSensorInfo =
146 {
147     .sensorName = "Camera Vsync",
148     .sensorType = SENS_TYPE_VSYNC,
149     .numAxis = NUM_AXIS_ONE,
150     .interrupt = NANOHUB_INT_NONWAKEUP,
151     .minSamples = 20,
152 };
153 
vsyncPower(bool on,void * cookie)154 static bool vsyncPower(bool on, void *cookie)
155 {
156     VERBOSE_PRINT("power %d\n", on);
157 
158     if (on) {
159         extiClearPendingGpio(mTask.pin);
160         enableInterrupt(mTask.pin, &mTask.isr);
161     } else {
162         disableInterrupt(mTask.pin, &mTask.isr);
163         extiClearPendingGpio(mTask.pin);
164     }
165 
166     mTask.on = on;
167     sensorSignalInternalEvt(mTask.sensorHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, on, 0);
168     return true;
169 }
170 
vsyncFirmwareUpload(void * cookie)171 static bool vsyncFirmwareUpload(void *cookie)
172 {
173     return sensorSignalInternalEvt(mTask.sensorHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
174 }
175 
vsyncSetRate(uint32_t rate,uint64_t latency,void * cookie)176 static bool vsyncSetRate(uint32_t rate, uint64_t latency, void *cookie)
177 {
178     VERBOSE_PRINT("setRate\n");
179     return sensorSignalInternalEvt(mTask.sensorHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
180 }
181 
vsyncFlush(void * cookie)182 static bool vsyncFlush(void *cookie)
183 {
184     VERBOSE_PRINT("flush\n");
185     return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_VSYNC), SENSOR_DATA_EVENT_FLUSH, NULL);
186 }
187 
188 static const struct SensorOps mSensorOps =
189 {
190     .sensorPower = vsyncPower,
191     .sensorFirmwareUpload = vsyncFirmwareUpload,
192     .sensorSetRate = vsyncSetRate,
193     .sensorFlush = vsyncFlush,
194 };
195 
handleEvent(uint32_t evtType,const void * evtData)196 static void handleEvent(uint32_t evtType, const void* evtData)
197 {
198 }
199 
startTask(uint32_t taskId)200 static bool startTask(uint32_t taskId)
201 {
202     mTask.id = taskId;
203     mTask.sensorHandle = sensorRegister(&mSensorInfo, &mSensorOps, NULL, true);
204     mTask.pin = gpioRequest(VSYNC_PIN);
205     mTask.isr.func = vsyncIsr;
206     mTask.isr.maxLatencyNs = MAX_VSYNC_INT_LATENCY;
207 
208     mTask.evtSlab = slabAllocatorNew(sizeof(struct SingleAxisDataEvent) + sizeof(struct SingleAxisDataPoint), 4, MAX_VSYNC_EVENTS);
209     if (!mTask.evtSlab) {
210         ERROR_PRINT("slabAllocatorNew() failed\n");
211         return false;
212     }
213 
214     return true;
215 }
216 
endTask(void)217 static void endTask(void)
218 {
219     disableInterrupt(mTask.pin, &mTask.isr);
220     extiUnchainIsr(VSYNC_IRQ, &mTask.isr);
221     extiClearPendingGpio(mTask.pin);
222     gpioRelease(mTask.pin);
223     sensorUnregister(mTask.sensorHandle);
224 }
225 
226 INTERNAL_APP_INIT(VSYNC_APP_ID, VSYNC_APP_VERSION, startTask, endTask, handleEvent);
227