00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <sys/types.h>
00004 #include <sys/stat.h>
00005 #include <sys/ioctl.h>
00006 #include <fcntl.h>
00007
00008 #include <linux/videodev2.h>
00009 #include <limits>
00010
00011 #include "FCam/N900/Lens.h"
00012 #include "FCam/Frame.h"
00013
00014 #include "../Debug.h"
00015 #include "V4L2Sensor.h"
00016
00017 namespace FCam {
00018 namespace N900 {
00019
00020 Lens::Lens() : lensHistory(512) {
00021
00022
00023 setFocus(0, -1);
00024 }
00025
00026 Lens::~Lens() {
00027 }
00028
00029
00030 int Lens::ioctlGet(unsigned key) {
00031 struct v4l2_control ctrl;
00032 ctrl.id = key;
00033 int fd = V4L2Sensor::instance("/dev/video0")->getFD();
00034 if (fd < 0) {
00035 V4L2Sensor::instance("/dev/video0")->open();
00036 fd = V4L2Sensor::instance("/dev/video0")->getFD();
00037 }
00038 if (ioctl(fd, VIDIOC_G_CTRL, &ctrl) < 0) {
00039 error(Event::DriverError, this, "VIDIOC_G_CTRL: %d, %d", key, errno);
00040 return -1;
00041 }
00042 return ctrl.value;
00043 }
00044
00045 int Lens::ioctlSet(unsigned key, int val) {
00046 struct v4l2_control ctrl;
00047 ctrl.id = key;
00048 ctrl.value = val;
00049 int fd = V4L2Sensor::instance("/dev/video0")->getFD();
00050 if (fd < 0) {
00051 V4L2Sensor::instance("/dev/video0")->open();
00052 fd = V4L2Sensor::instance("/dev/video0")->getFD();
00053 }
00054 if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) {
00055 error(Event::DriverError, this, "VIDIOC_S_CTRL: %d = %d, %d", key, val, errno);
00056 return -1;
00057 }
00058 if (ioctl(fd, VIDIOC_G_CTRL, &ctrl) < 0) {
00059 error(Event::DriverError, this, "VIDIOC_G_CTRL: %d, %d", key, errno);
00060 return -1;
00061 }
00062 return ctrl.value;
00063 }
00064
00065
00066 void Lens::setFocus(float f, float speed = -1) {
00067
00068
00069 if (speed < 0) { speed = maxFocusSpeed(); }
00070 if (speed < minFocusSpeed()) { speed = minFocusSpeed(); }
00071 if (speed > maxFocusSpeed()) { speed = maxFocusSpeed(); }
00072
00073
00074 ioctlSet(V4L2_CID_FOCUS_AD5820_RAMP_MODE, 0);
00075
00076
00077
00078 int val = ioctlSet(V4L2_CID_FOCUS_AD5820_RAMP_TIME, 1000000.0f/diopterRateToTickRate(speed));
00079
00080 float focusSpeed = tickRateToDiopterRate(1000000.0f / val);
00081
00082
00083 if (f < farFocus()) { f = farFocus(); }
00084 if (f > nearFocus()) { f = nearFocus(); }
00085
00086 int ticks = dioptersToTicks(f);
00087
00088 int oldTicks = ioctlGet(V4L2_CID_FOCUS_ABSOLUTE);
00089 float oldDiopters = ticksToDiopters(oldTicks);
00090
00091 int newTicks = ioctlSet(V4L2_CID_FOCUS_ABSOLUTE, ticks);
00092
00093 Time start = Time::now();
00094
00095 f = ticksToDiopters(newTicks);
00096 float dDiopters = f - oldDiopters;
00097 if (dDiopters < 0) { dDiopters = -dDiopters; }
00098
00099
00100 Time end = start + 1000000 * dDiopters / focusSpeed;
00101
00102 LensState s;
00103 s.time = start;
00104 s.position = oldDiopters;
00105 lensHistory.push(s);
00106 s.time = end;
00107 s.position = f;
00108 lensHistory.push(s);
00109 }
00110
00111 float Lens::getFocus() const {
00112 return getFocus(Time::now());
00113 }
00114
00115 float Lens::getFocus(Time t) const {
00116 if (lensHistory.size() && t > lensHistory[0].time) {
00117 return lensHistory[0].position;
00118 }
00119
00120 for (size_t i = 0; i < lensHistory.size()-1; i++) {
00121 if (t < lensHistory[i+1].time) { continue; }
00122 if (t < lensHistory[i].time) {
00123
00124 float alpha = float(t - lensHistory[i+1].time)/(lensHistory[i].time - lensHistory[i+1].time);
00125 return alpha * lensHistory[i].position + (1-alpha) * lensHistory[i+1].position;
00126 }
00127 }
00128
00129
00130 error(Event::LensHistoryError, "Lens position at time %d %d is unknown", t.s(), t.us());
00131 return std::numeric_limits<float>::quiet_NaN();
00132 }
00133
00134 bool Lens::focusChanging() const {
00135 Time t = Time::now();
00136 return (lensHistory.size()) && (lensHistory[0].time > t);
00137 }
00138
00139 float Lens::minFocusSpeed() const {
00140
00141 return tickRateToDiopterRate(1/0.003200f);
00142 }
00143
00144 float Lens::maxFocusSpeed() const {
00145
00146 return tickRateToDiopterRate(1/0.000050f);
00147 }
00148
00149
00150 float Lens::ticksToDiopters(int ticks) const {
00151 float d = 0.0315f*(ticks-227);
00152
00153
00154 if (d < 0.0f) { d = 0.0f; }
00155 if (d > 20.0f) { d = 20.0f; }
00156 return d;
00157 }
00158
00159 int Lens::dioptersToTicks(float diopter) const {
00160 return (int)(diopter*31.746f + 227.5f);
00161 }
00162
00163
00164 float Lens::tickRateToDiopterRate(int ticks) const {
00165 return ticks * 0.0315f;
00166 }
00167
00168 int Lens::diopterRateToTickRate(float diopter) const {
00169 return (int)(diopter*31.746f + 0.5f);
00170 }
00171
00172
00173 void Lens::tagFrame(FCam::Frame f) {
00174 float initialFocus = getFocus(f.exposureStartTime());
00175 float finalFocus = getFocus(f.exposureEndTime());
00176
00177 f["lens.initialFocus"] = initialFocus;
00178 f["lens.finalFocus"] = finalFocus;
00179 f["lens.focus"] = (initialFocus + finalFocus)/2;
00180 f["lens.focusSpeed"] = (1000000.0f * (finalFocus - initialFocus)/
00181 (f.exposureEndTime() - f.exposureStartTime()));
00182
00183 float zoom = getZoom();
00184 f["lens.zoom"] = zoom;
00185 f["lens.initialZoom"] = zoom;
00186 f["lens.finalZoom"] = zoom;
00187 f["lens.zoomSpeed"] = 0;
00188
00189 float aperture = getAperture();
00190 f["lens.aperture"] = aperture;
00191 f["lens.initialAperture"] = aperture;
00192 f["lens.finalAperture"] = aperture;
00193 f["lens.apertureSpeed"] = 0;
00194
00195
00196
00197
00198
00199
00200
00201 f["lens.minZoom"] = minZoom();
00202 f["lens.maxZoom"] = maxZoom();
00203 f["lens.wideApertureMin"] = wideAperture(minZoom());
00204 f["lens.wideApertureMax"] = wideAperture(maxZoom());
00205 }
00206
00207 }
00208 }