mt9v.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2009-2010, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of the Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 #include <wge100_camera/mt9v.h>
36 #include <ros/console.h>
37 #include <math.h>
38 #include <values.h>
39 
40 #define VMODEDEF(width, height, fps, hblank, vblank) { #width"x"#height"x"#fps, width, height, fps, hblank, vblank }
42  VMODEDEF(752,480,15, 974, 138),
43  VMODEDEF(752,480,12.5, 848, 320),
44  VMODEDEF(640,480,30, 372, 47),
45  VMODEDEF(640,480,25, 543, 61),
46  VMODEDEF(640,480,15, 873, 225),
47  VMODEDEF(640,480,12.5, 960, 320),
48  VMODEDEF(320,240,60, 106, 73),
49  VMODEDEF(320,240,50, 180, 80),
50  VMODEDEF(320,240,30, 332, 169),
51  VMODEDEF(320,240,25, 180, 400)
52 };
53 
54 class MT9VImagerImpl : public MT9VImager
55 {
56 protected:
58 
60  uint8_t reg_row_start_;
63  uint8_t reg_hblank_;
64  uint8_t reg_vblank_;
69  uint8_t reg_read_mode_;
72 
73 // Imager dependent bounds
76 
77 // Some bits are not always at the same position
80 
81 // Cached register values
82  uint16_t read_mode_cache_;
85  uint16_t *companding_mode_cache_;
87 
88  uint16_t imager_version_;
89  double line_time_;
90 
91  std::string model_;
92 
94 
95 public:
96  MT9VImagerImpl(IpCamList &cam) : camera_(cam)
97  {
98  reg_column_start_ = 0x01;
99  reg_row_start_ = 0x02;
100  reg_window_width_ = 0x04;
101  reg_window_height_ = 0x03;
102  reg_hblank_ = 0x05;
103  reg_vblank_ = 0x06;
104  reg_shutter_width_ = 0x0B;
105  reg_max_shutter_width_ = 0xBD;
106  reg_analog_gain_ = 0x35;
107  reg_agc_aec_enable_ = 0xAF;
108  reg_read_mode_ = 0x0D;
109  reg_companding_mode_ = 0x1C;
110  reg_desired_bin_ = 0xA5;
111 
112  agc_aec_enable_shift_ = 0;
113  companding_mode_shift_ = 0;
114 
115  max_max_shutter_width_ = 2047;
116  max_shutter_width_ = 32767;
117 
118  read_mode_cache_ = 0x300;
119  agc_aec_mode_cache_ = &agc_aec_mode_cache_backing_;
120  *agc_aec_mode_cache_ = 3;
121  companding_mode_cache_ = &companding_mode_cache_backing_;
122  *companding_mode_cache_ = 2;
123 
124  line_time_ = 0;
125 
126  if (wge100ReliableSensorRead(&cam, 0x00, &imager_version_, NULL))
127  {
128  ROS_WARN("MT9VImager::getInstance Unable to read imager version.");
129  }
130  //ROS_FATAL("Black level correction is forced off for debugging. This shouldn't get checked in.");
131  //setBlackLevel(true, 64, 0, 0);
132  }
133 
134  virtual ~MT9VImagerImpl()
135  {
136  }
137 
138  virtual bool setAgcAec(bool agc, bool aec)
139  {
140  uint16_t mask = 3 << agc_aec_enable_shift_;
141  uint16_t val = (agc ? 2 : 0) | (aec ? 1 : 0);
142  val <<= agc_aec_enable_shift_;
143 
144  *agc_aec_mode_cache_ = (*agc_aec_mode_cache_ & ~mask) | val;
145 
146  if (wge100ReliableSensorWrite(&camera_, reg_agc_aec_enable_, *agc_aec_mode_cache_, NULL) != 0)
147  {
148  ROS_WARN("Error setting AGC/AEC mode. Exposure and gain may be incorrect.");
149  return true;
150  }
151  return false;
152  }
153 
154  virtual bool setBrightness(int brightness)
155  {
156  if (wge100ReliableSensorWrite(&camera_, reg_desired_bin_, brightness, NULL) != 0)
157  {
158  ROS_WARN("Error setting brightness.");
159  return true;
160  }
161  return false;
162  }
163 
164  virtual bool setGain(int gain)
165  {
166  if (wge100ReliableSensorWrite(&camera_, reg_analog_gain_, 0x8000 | gain, NULL) != 0)
167  {
168  ROS_WARN("Error setting analog gain.");
169  return true;
170  }
171  return false;
172  }
173 
174  virtual bool setExposure(double exp)
175  {
176  if (line_time_ == 0)
177  {
178  ROS_ERROR("setExposure called before setMode in class MT9VImager. This is a bug.");
179  return true;
180  }
181  int explines = exp / line_time_;
182  if (explines < 1)
183  {
184  ROS_WARN("Requested exposure too short, setting to %f s", line_time_);
185  explines = 1;
186  }
187  if (explines > max_shutter_width_)
188  {
189  explines = max_shutter_width_;
190  ROS_WARN("Requested exposure too long, setting to %f s", explines * line_time_);
191  }
192  ROS_DEBUG("Setting exposure lines to %i (%f s).", explines, explines * line_time_);
193  if ( wge100ReliableSensorWrite( &camera_, reg_shutter_width_, explines, NULL) != 0)
194  {
195  ROS_WARN("Error setting exposure.");
196  return true;
197  }
198  return false;
199  }
200 
201  virtual bool setMaxExposure(double exp)
202  {
203  if (line_time_ == 0)
204  {
205  ROS_ERROR("setMaxExposure called before setMode in class MT9VImager. This is a bug.");
206  return true;
207  }
208  int explines = exp / line_time_;
209  if (explines < 1)
210  {
211  ROS_WARN("Requested max exposure too short, setting to %f s", line_time_);
212  explines = 1;
213  }
214  if (explines > max_max_shutter_width_)
215  {
216  explines = max_max_shutter_width_;
217  ROS_WARN("Requested max exposure too long, setting to %f s", explines * line_time_);
218  }
219  ROS_DEBUG("Setting max exposure lines to %i (%f s).", explines, explines * line_time_);
220  if ( wge100ReliableSensorWrite( &camera_, reg_max_shutter_width_, explines, NULL) != 0)
221  {
222  ROS_WARN("Error setting max exposure.");
223  return true;
224  }
225  return false;
226  }
227 
228  virtual bool setMirror(bool mirrorx, bool mirrory)
229  {
230  uint16_t mask = 0x30;
231  uint16_t val = (mirrory ? 0x10 : 0) | (mirrorx ? 0x20 : 0);
232 
233  read_mode_cache_ = (read_mode_cache_ & ~mask) | val;
234 
235  if (wge100ReliableSensorWrite(&camera_, reg_read_mode_, read_mode_cache_, NULL) != 0)
236  {
237  ROS_WARN("Error setting mirror mode. Read mode register settings may have been corrupted.");
238  return true;
239  }
240  return false;
241  }
242 
243  virtual bool setBlackLevel(bool manual_override, int calibration_value, int step_size, int filter_length)
244  {
245  if (wge100ReliableSensorWrite(&camera_, 0x47, ((filter_length & 7) << 5) | manual_override, NULL) != 0 ||
246  wge100ReliableSensorWrite(&camera_, 0x48, calibration_value & 0xFF, NULL) != 0 ||
247  wge100ReliableSensorWrite(&camera_, 0x4C, step_size & 0x1F, NULL) != 0)
248  {
249  ROS_WARN("Error setting black level correction mode.");
250  return true;
251  }
252 
253  return false;
254  }
255 
256  virtual bool setMode(int x, int y, int binx, int biny, double rate, int xoffset, int yoffset)
257  {
258  if (binx < 0 || binx > 2)
259  {
260  ROS_ERROR("x binning should 0, 1 or 2, not %i", binx);
261  return true;
262  }
263 
264  if (biny < 0 || biny > 2)
265  {
266  ROS_ERROR("y binning should 0, 1 or 2, not %i", biny);
267  return true;
268  }
269 
270  x <<= binx;
271  y <<= biny;
272 
273  if (x < 1 || x > 752)
274  {
275  ROS_ERROR("Requested x resolution (includes binning) %i is not between 1 and 752.", x);
276  return true;
277  }
278 
279  if (y < 1 || y > 480)
280  {
281  ROS_ERROR("Requested y resolution (includes binning) %i is not between 1 and 480.", y);
282  return true;
283  }
284 
285  // XXX -old center-based calculation left here for reference #4670
286  // startx = (752 - x) / 2 + xoffset + 1;
287  // starty = (480 - y) / 2 + yoffset + 4;
288 
289  int startx, starty;
290  startx = 57 + xoffset;
291  starty = 4 + yoffset;
292 
293  if (startx < 1 || startx + x > 752 + 1)
294  {
295  ROS_ERROR("Image x offset exceeds imager bounds.");
296  return true;
297  }
298 
299  if (starty < 4 || starty + y > 480 + 4)
300  {
301  ROS_ERROR("Image y offset exceeds imager bounds.");
302  return true;
303  }
304 
305  int bestvblank = 0;
306  int besthblank = 0;
307 
308  double clock = 16e6;
309  int target_tics = clock / rate;
310  int besterror = INT_MAX;
311  int packet_size = 70 + (x >> binx);
312  double max_peak_data_rate = 90e6;
313  double best_peak_data_rate = 0;
314  int best_tics = 0;
315  ROS_DEBUG("Target tics %i", target_tics);
316 
317  for (int hblank = 100; hblank < 1023; hblank++) // Smaller min values are possible depending on binning. Who cares...
318  {
319  int htics = x + hblank;
320  int extra_tics = 4;
321  int vblank = round(((double) target_tics - extra_tics) / htics) - y;
322  if (vblank < 40) // Could probably use 4 here
323  vblank = 40;
324  if (vblank > 3000) // Some imagers can do more
325  vblank = 3000;
326  int vtics = vblank + y;
327 
328  int tics = htics * vtics + extra_tics;
329  int err = abs(tics - target_tics);
330  double peak_data_rate = 8 * packet_size * clock / htics;
331 
332  if (peak_data_rate <= max_peak_data_rate && err < besterror)
333  {
334  besterror = err;
335  best_tics = tics;
336  bestvblank = vblank;
337  besthblank = hblank;
338  best_peak_data_rate = peak_data_rate;
339  }
340  }
341 
342  if (besterror == INT_MAX)
343  {
344  ROS_ERROR("Could not find suitable vblank and hblank for %ix%i mode.\n", x, y);
345  return true;
346  }
347 
348  line_time_ = (besthblank + x) / clock;
349 
350  ROS_DEBUG("Selected vblank=%i hblank=%i data_rate=%f err=%f period=%f", bestvblank, besthblank, best_peak_data_rate, besterror / clock, best_tics / clock);
351 
352  if (wge100ReliableSensorWrite(&camera_, reg_vblank_, bestvblank, NULL) != 0)
353  {
354  ROS_ERROR("Failed to set vertical blanking. Stream will probably be corrupt.");
355  return true;
356  }
357 
358  if (wge100ReliableSensorWrite(&camera_, reg_hblank_, besthblank, NULL) != 0)
359  {
360  ROS_ERROR("Failed to set horizontal blanking. Stream will probably be corrupt.");
361  return true;
362  }
363 
364  if (wge100ReliableSensorWrite(&camera_, reg_column_start_, startx, NULL) != 0)
365  {
366  ROS_ERROR("Failed to set start column. Stream will probably be corrupt.");
367  return true;
368  }
369 
370  if (wge100ReliableSensorWrite(&camera_, reg_row_start_, starty, NULL) != 0)
371  {
372  ROS_ERROR("Failed to set start row. Stream will probably be corrupt.");
373  return true;
374  }
375 
376  if (wge100ReliableSensorWrite(&camera_, reg_window_width_, x, NULL) != 0)
377  {
378  ROS_ERROR("Failed to set image width. Stream will probably be corrupt.");
379  return true;
380  }
381 
382  if (wge100ReliableSensorWrite(&camera_, reg_window_height_, y, NULL) != 0)
383  {
384  ROS_ERROR("Failed to set image height. Stream will probably be corrupt.");
385  return true;
386  }
387 
388  uint16_t mask = 0x0F;
389  uint16_t val = (binx << 2) | biny;
390 
391  read_mode_cache_ = (read_mode_cache_ & ~mask) | val;
392 
393  if (wge100ReliableSensorWrite(&camera_, reg_read_mode_, read_mode_cache_, NULL) != 0)
394  {
395  ROS_ERROR("Failed to set binning modes. Read mode may be corrupted.");
396  return true;
397  }
398 
399  return false;
400  }
401 
402  virtual bool setCompanding(bool activated)
403  {
404  uint16_t mask = 3 << companding_mode_shift_;
405  uint16_t val = (activated ? 3 : 2) << companding_mode_shift_;
406  *companding_mode_cache_ = (*companding_mode_cache_ & ~mask) | val;
407 
408  if (wge100ReliableSensorWrite(&camera_, reg_companding_mode_, *companding_mode_cache_, NULL) != 0)
409  {
410  ROS_WARN("Error setting companding mode.");
411  return true;
412  }
413  return false;
414  }
415 
417  {
418  return alternate_;
419  }
420 
421  virtual uint16_t getVersion()
422  {
423  return imager_version_;
424  }
425 
426  virtual std::string getModel()
427  {
428  return model_;
429  }
430 };
431 
432 class MT9V034 : public MT9VImagerImpl
433 {
434 public:
436  {
437  public:
439  {
440  }
441 
443  {
444  model_ = "MT9V034";
449  reg_column_start_ = 0xC9;
450  reg_row_start_ = 0x0CA;
451  reg_window_width_ = 0xCC;
452  reg_window_height_ = 0xCB;
453  reg_hblank_ = 0xCD;
454  reg_vblank_ = 0xCE;
455  reg_shutter_width_ = 0xD2;
456  reg_max_shutter_width_ = 0xAD; // FIXME Yes, they went and used the same max frame rate for both contexts! Why???
457  reg_analog_gain_ = 0x36;
458  reg_agc_aec_enable_ = 0xAF;
459  reg_read_mode_ = 0x0E;
460  }
461  };
462 
464  {
465  ROS_DEBUG("Found MT9V034 imager.");
466  model_ = "MT9V034";
467  max_max_shutter_width_ = 32765;
468  max_shutter_width_ = 32765;
469  reg_max_shutter_width_ = 0xAD;
470  *agc_aec_mode_cache_ = 0x303;
471  *companding_mode_cache_ = 0x302;
472  alternate_ = MT9VImagerPtr(new MT9V034Alternate(cam, this));
473 
474  if (wge100ReliableSensorWrite(&camera_, 0x18, 0x3e3a, NULL) ||
475  wge100ReliableSensorWrite(&camera_, 0x15, 0x7f32, NULL) ||
476  wge100ReliableSensorWrite(&camera_, 0x20, 0x01c1, NULL) ||
477  wge100ReliableSensorWrite(&camera_, 0x21, 0x0018, NULL))
478  {
479  ROS_WARN("Error setting magic sensor register.");
480  }
481  if (wge100ReliableSensorWrite(&camera_, 0x70, 0x000, NULL) != 0)
482  {
483  ROS_WARN("Error turning off row-noise correction.");
484  }
485  if (wge100ReliableSensorWrite(&camera_, 0x3A, 0x001A, NULL))
486  {
487  ROS_WARN("Error setting V2 Voltge level for context B.");
488  }
489  if (wge100ReliableSensorWrite(&camera_, 0x0F, 0x0000, NULL))
490  {
491  ROS_WARN("Error turning off high dynamic range for alternate configuration.");
492  }
493  if (wge100ReliableSensorWrite(&camera_, 0xD1, 0x0164, NULL))
494  {
495  ROS_WARN("Error turning on exposure knee auto-adjust for alternate configuration.");
496  }
497  }
498 
499  virtual ~MT9V034()
500  {
501  }
502 };
503 
504 class MT9V032 : public MT9VImagerImpl
505 {
506 public:
508  {
509  ROS_DEBUG("Found MT9V032 imager.");
510  model_ = "MT9V032";
511  if (wge100ReliableSensorWrite(&camera_, 0x18, 0x3e3a, NULL) ||
512  wge100ReliableSensorWrite(&camera_, 0x15, 0x7f32, NULL) ||
513  wge100ReliableSensorWrite(&camera_, 0x20, 0x01c1, NULL) ||
514  wge100ReliableSensorWrite(&camera_, 0x21, 0x0018, NULL))
515  {
516  ROS_WARN("Error setting magic sensor register.");
517  }
518  if (wge100ReliableSensorWrite(&camera_, 0x70, 0x14, NULL) != 0)
519  {
520  ROS_WARN("Error turning off row-noise correction");
521  }
522  }
523 
524  virtual ~MT9V032()
525  {
526  }
527 };
528 
530 {
531  uint16_t imager_version;
532  if (wge100ReliableSensorRead(&cam, 0x00, &imager_version, NULL))
533  {
534  ROS_ERROR("MT9VImager::getInstance Unable to read imager version.");
535  return MT9VImagerPtr();
536  }
537 
538  switch (imager_version)
539  {
540  case 0x1324:
541  return MT9VImagerPtr(new MT9V034(cam));
542 
543  default:
544  ROS_ERROR("MT9VImager::getInstance Unknown imager version 0x%04x. Assuming it is compatible with MT9V032.", imager_version);
545  return MT9VImagerPtr();
546 
547  case 0x1311:
548  case 0x1313:
549  return MT9VImagerPtr(new MT9V032(cam));
550  }
551 }
552 
553 
virtual bool setMaxExposure(double exp)
Definition: mt9v.cpp:201
uint16_t read_mode_cache_
Definition: mt9v.cpp:82
const struct MT9VMode MT9VModes[MT9V_NUM_MODES]
Definition: mt9v.cpp:41
MT9VImagerImpl(IpCamList &cam)
Definition: mt9v.cpp:96
MT9V034Alternate(IpCamList &cam, MT9V034 *parent)
Definition: mt9v.cpp:442
uint8_t reg_shutter_width_
Definition: mt9v.cpp:65
Definition: mt9v.h:68
uint8_t reg_companding_mode_
Definition: mt9v.cpp:70
virtual bool setGain(int gain)
Definition: mt9v.cpp:164
uint16_t * companding_mode_cache_
Definition: mt9v.cpp:84
int max_max_shutter_width_
Definition: mt9v.cpp:74
uint16_t companding_mode_cache_backing_
Definition: mt9v.cpp:86
uint8_t reg_column_start_
Definition: mt9v.cpp:59
IpCamList & camera_
Definition: mt9v.cpp:57
uint8_t reg_row_start_
Definition: mt9v.cpp:60
virtual ~MT9V032()
Definition: mt9v.cpp:524
int wge100ReliableSensorRead(const IpCamList *camInfo, uint8_t reg, uint16_t *data, int *retries)
Definition: wge100lib.c:1349
int wge100ReliableSensorWrite(const IpCamList *camInfo, uint8_t reg, uint16_t data, int *retries)
Definition: wge100lib.c:1252
#define ROS_WARN(...)
virtual bool setCompanding(bool activated)
Definition: mt9v.cpp:402
#define VMODEDEF(width, height, fps, hblank, vblank)
Definition: mt9v.cpp:40
uint16_t imager_version_
Definition: mt9v.cpp:86
virtual bool setMode(int x, int y, int binx, int biny, double rate, int xoffset, int yoffset)
Definition: mt9v.cpp:256
uint16_t agc_aec_mode_cache_backing_
Definition: mt9v.cpp:84
virtual MT9VImagerPtr getAlternateContext()
Definition: mt9v.cpp:416
int agc_aec_enable_shift_
Definition: mt9v.cpp:78
uint8_t reg_read_mode_
Definition: mt9v.cpp:69
double line_time_
Definition: mt9v.cpp:89
virtual bool setExposure(double exp)
Definition: mt9v.cpp:174
virtual ~MT9VImagerImpl()
Definition: mt9v.cpp:134
virtual uint16_t getVersion()
Definition: mt9v.cpp:421
int max_shutter_width_
Definition: mt9v.cpp:75
virtual bool setBrightness(int brightness)
Definition: mt9v.cpp:154
boost::shared_ptr< MT9VImager > MT9VImagerPtr
Definition: mt9v.h:79
MT9VImagerPtr alternate_
Definition: mt9v.cpp:93
int companding_mode_shift_
Definition: mt9v.cpp:79
uint8_t reg_analog_gain_
Definition: mt9v.cpp:67
virtual bool setMirror(bool mirrorx, bool mirrory)
Definition: mt9v.cpp:228
std::string model_
Definition: mt9v.cpp:91
uint8_t reg_desired_bin_
Definition: mt9v.cpp:71
uint16_t * agc_aec_mode_cache_
Definition: mt9v.cpp:83
uint8_t reg_agc_aec_enable_
Definition: mt9v.cpp:68
#define MT9V_NUM_MODES
Definition: mt9v.h:66
virtual bool setBlackLevel(bool manual_override, int calibration_value, int step_size, int filter_length)
Definition: mt9v.cpp:243
static MT9VImagerPtr getInstance(IpCamList &cam)
Definition: mt9v.cpp:529
uint8_t reg_window_height_
Definition: mt9v.cpp:62
MT9V034(IpCamList &cam)
Definition: mt9v.cpp:463
uint8_t reg_max_shutter_width_
Definition: mt9v.cpp:66
virtual std::string getModel()
Definition: mt9v.cpp:426
virtual ~MT9V034()
Definition: mt9v.cpp:499
uint8_t reg_window_width_
Definition: mt9v.cpp:61
#define ROS_ERROR(...)
uint8_t reg_hblank_
Definition: mt9v.cpp:63
uint8_t reg_vblank_
Definition: mt9v.cpp:64
virtual bool setAgcAec(bool agc, bool aec)
Definition: mt9v.cpp:138
MT9V032(IpCamList &cam)
Definition: mt9v.cpp:507
#define ROS_DEBUG(...)


wge100_camera
Author(s): Blaise Gassend, Patrick Mihelich, Eric MacIntosh, David Palchak
autogenerated on Mon Jun 10 2019 15:44:15