ZED Open Capture  v0.6.0
Low level camera driver for the ZED stereo camera family
videocapture.cpp
Go to the documentation of this file.
1 //
3 // Copyright (c) 2021, STEREOLABS.
4 //
5 // All rights reserved.
6 //
7 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
8 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
10 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
11 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
12 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
13 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
14 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
15 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
16 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
17 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
18 //
20 
21 #include "videocapture.hpp"
22 
23 #ifdef SENSORS_MOD_AVAILABLE
24 #include "sensorcapture.hpp"
25 #endif
26 
27 #include <sys/stat.h> // for stat, S_ISCHR
28 #include <errno.h> // for errno, EBADRQC, EINVAL, ENOBUFS, ENOENT
29 #include <fcntl.h> // for open, O_NONBLOCK, O_RDONLY, O_RDWR
30 #include <unistd.h> // for usleep, close
31 
32 #include <linux/usb/video.h> // for UVC_GET_CUR, UVC_SET_CUR, UVC_GET_LEN
33 #include <linux/uvcvideo.h> // for uvc_xu_control_query, UVCIOC_CTRL_QUERY
34 #include <linux/videodev2.h> // for v4l2_buffer, v4l2_queryctrl, V4L2_BUF_T...
35 #include <sys/mman.h> // for mmap, munmap, MAP_SHARED, PROT_READ
36 #include <sys/ioctl.h> // for ioctl
37 
38 #include <sstream>
39 #include <fstream> // for char_traits, basic_istream::operator>>
40 
41 #include <cmath> // for round
42 
43 #define IOCTL_RETRY 3
44 
45 #define READ_MODE 1
46 #define WRITE_MODE 2
47 
48 // ----> Camera control
49 #define cbs_xu_unit_id 0x04 //mapped to wIndex 0x0400
50 #define cbs_xu_control_selector 0x02 //mapped to wValue 0x0200
51 
52 #define ISP_CTRL_LEFT 0x80181033
53 #define ISP_CTRL_RIGHT 0x80181833
54 
55 #define AEG_AGC_MASK_ON 0x02
56 #define AEG_AGC_MASK_OFF 0xFD
57 
58 #define ADDR_EXP_H 0x3500
59 #define ADDR_EXP_M 0x3501
60 #define ADDR_EXP_L 0x3502
61 #define ADDR_GAIN_H 0x3507
62 #define ADDR_GAIN_M 0x3508
63 #define ADDR_GAIN_L 0x3509
64 
65 #define XU_TASK_SET 0x50
66 #define XU_TASK_GET 0x51
67 #define XU_ISP_CTRL 0x07
68 #define XU_EXP_GAIN 0x25
69 
70 #define UNIQUE_ID_START 0x18000
71 
72 #define LINUX_CTRL_BRIGHTNESS 9963776
73 #define LINUX_CTRL_CONTRAST 9963777
74 #define LINUX_CTRL_HUE 9963779
75 #define LINUX_CTRL_SATURATION 9963778
76 #define LINUX_CTRL_GAIN 9963795
77 #define LINUX_CTRL_AWB 9963802
78 #define LINUX_CTRL_AWB_AUTO 9963788
79 #define LINUX_CTRL_SHARPNESS 9963803
80 #define LINUX_CTRL_GAMMA 9963792
81 
82 #define DEFAULT_GAMMA_NOECT 1
83 #define DEFAULT_MIN_GAMMA 1
84 #define DEFAULT_MAX_GAMMA 9
85 
86 #define DEFAULT_MIN_GAIN 0
87 #define DEFAULT_MAX_GAIN 100
88 #define DEFAULT_MIN_EXP 0
89 #define DEFAULT_MAX_EXP 100
90 
91 // Gain working zones
92 #define GAIN_ZONE1_MIN 0
93 #define GAIN_ZONE1_MAX 255
94 #define GAIN_ZONE2_MIN 378
95 #define GAIN_ZONE2_MAX 511
96 #define GAIN_ZONE3_MIN 890
97 #define GAIN_ZONE3_MAX 1023
98 #define GAIN_ZONE4_MIN 1914
99 #define GAIN_ZONE4_MAX 2047
100 
101 // Raw exposure max values
102 #define EXP_RAW_MAX_15FPS 1550
103 #define EXP_RAW_MAX_30FPS 1100
104 #define EXP_RAW_MAX_60FPS 880
105 #define EXP_RAW_MAX_100FPS 720
106 
107 #define EXP_RAW_MIN 2
108 // <---- Camera Control
109 
110 
111 namespace sl_oc {
112 
113 namespace video {
114 
116 {
117  memcpy( &mParams, &params, sizeof(VideoParams) );
118 
119  if( mParams.verbose )
120  {
121  std::string ver =
122  "ZED Open Capture - Camera module - Version: "
123  + std::to_string(mMajorVer) + "."
124  + std::to_string(mMinorVer) + "."
125  + std::to_string(mPatchVer);
126  INFO_OUT(mParams.verbose,ver);
127  }
128 
129  // Check that FPS is coherent with user resolution
130  checkResFps( );
131 
132  // Calculate gain zones (required because the raw gain control is not continuous in the range of values)
133  mGainSegMax = (GAIN_ZONE4_MAX-GAIN_ZONE4_MIN)+(GAIN_ZONE3_MAX-GAIN_ZONE3_MIN)+(GAIN_ZONE2_MAX-GAIN_ZONE2_MIN)+(GAIN_ZONE1_MAX-GAIN_ZONE1_MIN);
134 
135  // FPS mapping
136  if( mFps <= 15 )
137  mExpoureRawMax = EXP_RAW_MAX_15FPS;
138  else if( mFps <= 30 )
139  mExpoureRawMax = EXP_RAW_MAX_30FPS;
140  else if( mFps <= 60 )
141  mExpoureRawMax = EXP_RAW_MAX_60FPS;
142  else
143  mExpoureRawMax = EXP_RAW_MAX_100FPS;
144 }
145 
147 {
148  reset();
149 }
150 
151 void VideoCapture::reset()
152 {
153  setLEDstatus( false );
154 
155  mStopCapture = true;
156 
157  if( mGrabThread.joinable() )
158  {
159  mGrabThread.join();
160  }
161 
162  // ----> Stop capturing
163  enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
164  if (mFileDesc != -1)
165  xioctl(mFileDesc, VIDIOC_STREAMOFF, &type);
166  // <---- Stop capturing
167 
168  // ----> deinit device
169  if( mInitialized && mBuffers)
170  {
171  for (unsigned int i = 0; i < mBufCount; ++i)
172  munmap(mBuffers[i].start, mBuffers[i].length);
173  if (mBuffers)
174  free(mBuffers);
175 
176  mBuffers = nullptr;
177  }
178  // <---- deinit device
179 
180  if (mFileDesc)
181  {
182  close(mFileDesc);
183  mFileDesc=-1;
184  }
185 
186  if(mLastFrame.data)
187  {
188  delete [] mLastFrame.data;
189  mLastFrame.data = nullptr;
190  }
191 
192  if( mParams.verbose && mInitialized)
193  {
194  std::string msg = "Device closed";
195  INFO_OUT(mParams.verbose,msg );
196  }
197 
198  mInitialized=false;
199 }
200 
201 void VideoCapture::checkResFps()
202 {
203  mWidth = cameraResolution[static_cast<int>(mParams.res)].width*2;
204  mHeight = cameraResolution[static_cast<int>(mParams.res)].height;
205  mFps = static_cast<int>(mParams.fps);
206 
207  switch (mParams.res)
208  {
209  default:
210  WARNING_OUT(mParams.verbose,"RESOLUTION not supported. Using the best value");
211 
212  case RESOLUTION::HD2K:
213  if( mFps!=15 )
214  {
215  WARNING_OUT(mParams.verbose,"FPS not supported for the chosen resolution. Using the best value");
216  mFps = 15;
217  }
218  break;
219 
220  case RESOLUTION::HD1080:
221  if( mFps!=15 && mFps!=30 )
222  {
223  WARNING_OUT(mParams.verbose,"FPS not supported for the chosen resolution. Using the best value");
224 
225  if( mFps <= 22 )
226  mFps = 15;
227  else
228  mFps = 30;
229  }
230  break;
231 
232  case RESOLUTION::HD720:
233  if( mFps!=15 && mFps!=30 && mFps!=60 )
234  {
235  WARNING_OUT(mParams.verbose,"FPS not supported for the chosen resolution. Using the best value");
236 
237  if( mFps <= 22 )
238  mFps = 15;
239  else if( mFps < 45 )
240  mFps = 30;
241  else
242  mFps = 60;
243  }
244  break;
245 
246  case RESOLUTION::VGA:
247  if( mFps!=15 && mFps!=30 && mFps!=60 && mFps!=100)
248  {
249  WARNING_OUT(mParams.verbose,"FPS not supported for the chosen resolution. Using the best value");
250 
251  if( mFps <= 22 )
252  mFps = 15;
253  else if( mFps < 45 )
254  mFps = 30;
255  else if( mFps < 80 )
256  mFps = 60;
257  else
258  mFps = 100;
259  }
260  }
261 
262  if(mParams.verbose)
263  {
264  std::string msg = std::string("Camera resolution: ")
265  + std::to_string(mWidth)
266  + std::string("x")
267  + std::to_string(mHeight)
268  + std::string("@")
269  + std::to_string(mFps)
270  +std::string("Hz");
271 
272  INFO_OUT(mParams.verbose,msg);
273  }
274 }
275 
276 bool VideoCapture::initializeVideo( int devId/*=-1*/ )
277 {
278  reset();
279 
280  bool opened=false;
281 
282  if( devId==-1 )
283  {
284  // Try to open all the devices until the first success (max allowed by v4l: 64)
285  for( uint8_t id=0; id<64; id++ )
286  {
287  opened = openCamera( id );
288  if(opened) break;
289  }
290  }
291  else
292  {
293  opened = openCamera( static_cast<uint8_t>(devId) );
294  }
295 
296  if(!opened)
297  {
298  return false;
299  }
300 
301  mInitialized = startCapture();
302 
303  if( mParams.verbose && mInitialized)
304  {
305  std::string msg = "Device '" + mDevName + "' opened";
306  INFO_OUT(mParams.verbose,msg );
307  }
308 
309  setLEDstatus( true );
310 
311  resetAECAGC();
313  resetBrightness();
314  resetContrast();
315  resetGamma();
316  resetHue();
317  resetSaturation();
318  resetSharpness();
319 
320  return mInitialized;
321 }
322 
323 bool VideoCapture::openCamera( uint8_t devId )
324 {
325  mDevId = devId;
326 
327  mDevName = std::string("/dev/video") + std::to_string(mDevId);
328 
329  if( mParams.verbose )
330  {
331  std::string msg = "Trying to open the device '" + mDevName + "'";
332  INFO_OUT(mParams.verbose,msg );
333  }
334 
335  // Check camera model
336  mCameraModel = getCameraModel(mDevName);
337 
338  if( mCameraModel==SL_DEVICE::NONE )
339  {
340  if(mParams.verbose)
341  {
342  std::string msg = "The device '" + mDevName + "' is not a Stereolabs camera";
343  WARNING_OUT(mParams.verbose,msg );
344  }
345  return false;
346  }
347 
348  if( mCameraModel==SL_DEVICE::ZED ||
349  mCameraModel==SL_DEVICE::ZED_M )
350  {
351  if(mParams.verbose)
352  {
353  std::string msg = "The FW of the device '" + mDevName + "' is not supported. Please update it.";
354  ERROR_OUT(mParams.verbose,msg );
355  }
356  return false;
357  }
358 
359  // ----> Open
360  struct stat st;
361  memset(&st, 0, sizeof (struct stat));
362  if (-1 == stat(mDevName.c_str(), &st))
363  {
364  if(mParams.verbose)
365  {
366  std::string msg = std::string("Cannot identify '") + mDevName + "': ["
367  + std::to_string(errno) +std::string("] ") + std::string(strerror(errno));
368  ERROR_OUT(mParams.verbose,msg);
369 
370  return false;
371  }
372  }
373 
374  if (!S_ISCHR(st.st_mode))
375  {
376  if(mParams.verbose)
377  {
378  std::string msg = mDevName + std::string(" is no device");
379  ERROR_OUT(mParams.verbose,msg);
380 
381  return false;
382  }
383  }
384 
385  mFileDesc = 0;
386 
387  mFileDesc = open(mDevName.c_str(), O_RDWR|O_NONBLOCK,0); // Reading are non blocking
388 
389  if (-1 == mFileDesc)
390  {
391  if(mParams.verbose)
392  {
393  std::string msg = std::string("Cannot open '") + mDevName + "': ["
394  + std::to_string(errno) + std::string("] ") + std::string(strerror(errno));
395  ERROR_OUT(mParams.verbose,msg);
396  }
397 
398  return false;
399  }
400  // <---- Open
401 
402  int sn = getSerialNumber();
403  if(mParams.verbose)
404  {
405  std::string msg = std::string("Opened camera with SN: ") + std::to_string(sn);
406  INFO_OUT(mParams.verbose,msg);
407  }
408 
409  // ----> Init
410  struct v4l2_capability cap;
411  memset(&cap, 0, sizeof (v4l2_capability));
412  struct v4l2_cropcap cropcap;
413  memset(&cropcap, 0, sizeof (v4l2_cropcap));
414  struct v4l2_crop crop;
415  memset(&crop, 0, sizeof (v4l2_crop));
416  struct v4l2_format fmt;
417  memset(&fmt, 0, sizeof (v4l2_format));
418 
419  if( -1==xioctl(mFileDesc, VIDIOC_QUERYCAP, &cap) )
420  {
421  if(mParams.verbose)
422  {
423  std::string msg = std::string("Cannot query capabilities of '") + mDevName + "': ["
424  + std::to_string(errno) +std::string("] ") + std::string(strerror(errno));
425  ERROR_OUT(mParams.verbose,msg);
426  }
427 
428  return false;
429  }
430 
431  cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
432 
433  // Query the Capture
434  if (0 == xioctl(mFileDesc, VIDIOC_CROPCAP, &cropcap))
435  {
436  crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
437  crop.c = cropcap.defrect; /* reset to default */
438  }
439 
440  fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
441  fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
442  fmt.fmt.pix.field = V4L2_FIELD_ANY;
443 
444  if (mWidth * mHeight != 0)
445  {
446  fmt.fmt.pix.width = mWidth;
447  fmt.fmt.pix.height = mHeight;
448  }
449 
450  int width_tmp = mWidth;
451  int height_tmp = mHeight;
452 
453  /* Preserve original settings as set by v4l2-ctl for example */
454  if( -1==xioctl(mFileDesc, VIDIOC_S_FMT/*VIDIOC_G_FMT*/, &fmt) )
455  {
456  if(mParams.verbose)
457  {
458  std::string msg = std::string("Cannot set pixel format of '") + mDevName + "': ["
459  + std::to_string(errno) +std::string("] ") + std::string(strerror(errno));
460  ERROR_OUT(mParams.verbose,msg);
461  }
462 
463  return false;
464  }
465 
466  mWidth = fmt.fmt.pix.width;
467  mHeight = fmt.fmt.pix.height;
468  mChannels = fmt.fmt.pix.bytesperline / mWidth;
469 
470  // Asked resolution not available, exiting
471  if (mWidth != width_tmp || mHeight != height_tmp)
472  {
473  ERROR_OUT(mParams.verbose,"Error setting the camera resolution");
474  return false;
475  }
476 
477  if( -1==input_set_framerate(mFps) )
478  {
479  ERROR_OUT(mParams.verbose,"Error setting the camera framerate");
480  }
481 
482  // ----> Output frame allocation
483  mLastFrame.width = mWidth;
484  mLastFrame.height = mHeight;
485  mLastFrame.channels = mChannels;
486  int bufSize = mLastFrame.width * mLastFrame.height * mLastFrame.channels;
487  mLastFrame.data = new unsigned char[bufSize];
488  // <---- Output frame allocation
489 
490  struct v4l2_requestbuffers req;
491  memset(&req, 0, sizeof (v4l2_requestbuffers));
492 
493  req.count = mBufCount;
494 
495  req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
496  req.memory = V4L2_MEMORY_MMAP;
497  if( -1==xioctl(mFileDesc, VIDIOC_REQBUFS, &req) )
498  {
499  if(mParams.verbose)
500  {
501  std::string msg = std::string("Cannot request buffers for '") + mDevName + "': ["
502  + std::to_string(errno) +std::string("] ") + std::string(strerror(errno));
503  ERROR_OUT(mParams.verbose,msg);
504  }
505 
506  return false;
507  }
508 
509  // Create buffers
510  mBuffers = (UVCBuffer*) calloc(req.count, sizeof(*mBuffers));
511 
512  for(mBufCount = 0; mBufCount < req.count; ++mBufCount)
513  {
514  struct v4l2_buffer buf;
515  memset(&buf, 0, sizeof (v4l2_buffer));
516  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
517  buf.memory = V4L2_MEMORY_MMAP;
518  buf.index = mBufCount;
519  buf.flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
520  if( -1==xioctl(mFileDesc, VIDIOC_QUERYBUF, &buf))
521  {
522  if(mParams.verbose)
523  {
524  std::string msg = std::string("Cannot query buffer for '") + mDevName + "': ["
525  + std::to_string(errno) +std::string("] ") + std::string(strerror(errno));
526  ERROR_OUT(mParams.verbose,msg);
527  }
528 
529  return false;
530  }
531 
532  mBuffers[mBufCount].length = buf.length;
533 
534  mBuffers[mBufCount].start =
535  mmap(nullptr /* start anywhere */,
536  buf.length,
537  PROT_READ | PROT_WRITE /* required */,
538  MAP_SHARED /* recommended */,
539  mFileDesc, buf.m.offset);
540  }
541 
542  mBufCount = req.count;
543  // <---- Init
544 
545  return true;
546 }
547 
549 {
550  /*if(!mInitialized)
551  return -1;*/
552 
553  int ulValue = -1;
554 
555  uint8_t UNIQUE_BUF[384];
556  memset(UNIQUE_BUF, 0, 384);
557 
558  int res = -1;
559 
560  int try_count = 0;
561  while(res!=0)
562  {
563  res = ll_SPI_FlashProgramRead(&UNIQUE_BUF[0], UNIQUE_ID_START, 64, true);
564 
565  //check bytes read
566  if (UNIQUE_BUF[0] != 'O') {
567  res = -1;
568  }
569  if (UNIQUE_BUF[1] != 'V') {
570  res = -1;
571  }
572 
573  try_count++;
574  if (try_count>500)
575  break;
576  usleep(1000);
577  }
578 
579  if (res != 0)
580  return -1;
581 
582  //check bytes read
583  if (UNIQUE_BUF[0] != 'O') {
584  return -1;
585  }
586  if (UNIQUE_BUF[1] != 'V') {
587  return -1;
588  }
589 
590  ulValue = (UNIQUE_BUF[2] << 24) + (UNIQUE_BUF[3] << 16) + (UNIQUE_BUF[4] << 8) + UNIQUE_BUF[5];
591 
592  char buff[128];
593  memset(buff, 0, 128);
594  sprintf(buff, "%x", ulValue);
595  return (int) atoi(buff);
596 }
597 
598 bool VideoCapture::startCapture()
599 {
600  // ----> Start capturing
601  enum v4l2_buf_type type;
602  for (unsigned int i = 0; i < mBufCount; ++i)
603  {
604  struct v4l2_buffer buf = {0};
605  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
606  buf.memory = V4L2_MEMORY_MMAP;
607  buf.index = i;
608  if( -1==xioctl(mFileDesc, VIDIOC_QBUF, &buf) )
609  {
610  if(mParams.verbose)
611  {
612  std::string msg = std::string("Cannot queue buffer for '") + mDevName + "': ["
613  + std::to_string(errno) +std::string("] ") + std::string(strerror(errno));
614  ERROR_OUT(mParams.verbose,msg);
615  }
616 
617  return false;
618  }
619  }
620  type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
621 
622  // Set priority
623  int priority = V4L2_PRIORITY_RECORD;
624  if( -1==xioctl(mFileDesc, VIDIOC_G_PRIORITY, &priority) )
625  {
626  if(mParams.verbose)
627  {
628  std::string msg = std::string("Cannot set priority for '") + mDevName + "': ["
629  + std::to_string(errno) +std::string("] ") + std::string(strerror(errno));
630  ERROR_OUT(mParams.verbose,msg);
631  }
632 
633  return false;
634  }
635 
636  // Start streaming
637  if( -1==xioctl(mFileDesc, VIDIOC_STREAMON, &type) )
638  {
639  if(mParams.verbose)
640  {
641  std::string msg = std::string("Cannot start streaming for '") + mDevName + "': ["
642  + std::to_string(errno) +std::string("] ") + std::string(strerror(errno));
643  ERROR_OUT(mParams.verbose,msg);
644  }
645 
646  return false;
647  }
648  // <---- Start capturing
649 
650  mGrabThread = std::thread( &VideoCapture::grabThreadFunc,this );
651 
652  return true;
653 }
654 
655 int VideoCapture::input_set_framerate(int fps)
656 {
657  struct v4l2_streamparm streamparm = {0}; // v4l2 stream parameters struct
658 
659  streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
660  streamparm.parm.capture.capturemode |= V4L2_CAP_TIMEPERFRAME;
661  streamparm.parm.capture.timeperframe.numerator = 1;
662  streamparm.parm.capture.timeperframe.denominator = fps;
663 
664  return xioctl(mFileDesc, VIDIOC_S_PARM, &streamparm);
665 }
666 
667 int VideoCapture::xioctl(int fd, uint64_t IOCTL_X, void *arg)
668 {
669  int ret = 0;
670  int tries = IOCTL_RETRY;
671  do
672  {
673  ret = ioctl(fd, IOCTL_X, arg);
674  // usleep(1);
675  } while (ret && tries-- &&
676  ((errno == EINTR) || (errno == EAGAIN) || (errno == ETIMEDOUT)));
677 
678  if( ret==-1 )
679  {
680  if(mParams.verbose)
681  {
682  perror( "xioctl");
683  }
684  }
685 
686  return (ret);
687 }
688 
689 SL_DEVICE VideoCapture::getCameraModel( std::string dev_name)
690 {
692  int vid = 0, pid = 0;
693  std::string modalias = "";
694  std::string name = dev_name.erase(0, 5); //remove /dev/
695  if (!(std::ifstream("/sys/class/video4linux/" + name + "/device/modalias") >> modalias))
696  {
697  if(mParams.verbose>sl_oc::VERBOSITY::ERROR)
698  {
699  std::string msg =
700  std::string(" Not a modalias : /sys/class/video4linux/")
701  + name + std::string("/device/modalias");
702  WARNING_OUT(mParams.verbose,msg);
703  }
704  return camera_device;
705  }
706 
707  if (modalias.size() < 14 || modalias.substr(0, 5) != "usb:v" || modalias[9] != 'p')
708  {
709  if(mParams.verbose)
710  {
711  std::string msg = std::string(" not a modalias 2" );
712  WARNING_OUT(mParams.verbose,msg);
713  }
714  return camera_device;
715  }
716 
717  if (!(std::istringstream(modalias.substr(5, 4)) >> std::hex >> vid))
718  {
719  if(mParams.verbose)
720  {
721  std::string msg = std::string("unable to read Vendor ID" );
722  WARNING_OUT(mParams.verbose,msg);
723  }
724 
725 
726  return camera_device;
727  }
728 
729  if (!(std::istringstream(modalias.substr(10, 4)) >> std::hex >> pid))
730  {
731  if(mParams.verbose)
732  {
733  std::string msg = std::string("unable to read Product ID" );
734  WARNING_OUT(mParams.verbose,msg);
735  }
736 
737  return camera_device;
738  }
739 
740  // check PID VID
741  if (pid == SL_USB_PROD_ZED_REVA && vid == SL_USB_VENDOR)
742  camera_device = SL_DEVICE::ZED;
743  else if (pid == SL_USB_PROD_ZED_M_REVA && vid == SL_USB_VENDOR)
744  camera_device = SL_DEVICE::ZED_M;
745  else if (pid == SL_USB_PROD_ZED_REVB && vid == SL_USB_VENDOR)
746  camera_device = SL_DEVICE::ZED_CBS;
747  else if (pid == SL_USB_PROD_ZED_M_REVB && vid == SL_USB_VENDOR)
748  camera_device = SL_DEVICE::ZED_M_CBS;
749  else if (pid == SL_USB_PROD_ZED_2_REVB && vid == SL_USB_VENDOR)
750  camera_device = SL_DEVICE::ZED_2;
751  else if (pid == SL_USB_PROD_ZED_2i && vid == SL_USB_VENDOR)
752  camera_device = SL_DEVICE::ZED_2i;
753 
754  return camera_device;
755 }
756 
757 void VideoCapture::grabThreadFunc()
758 {
759  mNewFrame = false;
760  mStopCapture = false;
761 
762  fd_set fds;
763  struct timeval tv = {0};
764 
765  FD_ZERO(&fds);
766 
767  if (mFileDesc < 0)
768  return;
769 
770  FD_SET(mFileDesc, &fds);
771  tv.tv_sec = 2;
772  tv.tv_usec = 0;
773  select(mFileDesc + 1, &fds, nullptr, nullptr, &tv);
774 
775  struct v4l2_buffer buf;
776  memset(&(buf), 0, sizeof (buf));
777  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
778  buf.memory = V4L2_MEMORY_MMAP;
779  buf.bytesused = -1;
780  buf.length = 0;
781 
782  uint64_t rel_ts = 0;
783  int capture_frame_count = 0;
784 
785  mFirstFrame=true;
786 
787  while (!mStopCapture)
788  {
789  mGrabRunning=true;
790 
791  mComMutex.lock();
792  int ret = ioctl(mFileDesc, VIDIOC_DQBUF, &buf);
793  mComMutex.unlock();
794 
795  if (buf.bytesused == buf.length && ret == 0 && buf.index < mBufCount)
796  {
797  mCurrentIndex = buf.index;
798  // get buffer timestamp in us
799 
800  uint64_t ts_uvc = ((uint64_t) buf.timestamp.tv_sec) * (1000 * 1000) + ((uint64_t) buf.timestamp.tv_usec);
801 
802  if(mFirstFrame)
803  {
804  mStartTs = getWallTimestamp();
805  //std::cout << "VideoCapture: " << mStartTs << std::endl;
806 
807 #ifdef SENSORS_MOD_AVAILABLE
808  if(mSyncEnabled && mSensPtr)
809  {
810  // Synchronize reference timestamp
811  mSensPtr->setStartTimestamp(mStartTs);
812  }
813 #endif
814 
815  mFirstFrame = false;
816  mInitTs = ts_uvc;
817  }
818 
819  rel_ts = ts_uvc - mInitTs;
820  // cvt to ns
821  rel_ts *= 1000;
822 
823  mBufMutex.lock();
824  if (mLastFrame.data != nullptr && mWidth != 0 && mHeight != 0 && mBuffers[mCurrentIndex].start != nullptr)
825  {
826  mLastFrame.frame_id++;
827  memcpy(mLastFrame.data, (unsigned char*) mBuffers[mCurrentIndex].start, mBuffers[mCurrentIndex].length);
828  mLastFrame.timestamp = mStartTs + rel_ts;
829 
830  // static uint64_t last_ts=0;
831  // std::cout << "[Video] Frame TS: " << static_cast<double>(mLastFrame.timestamp)/1e9 << " sec" << std::endl;
832  // double dT = static_cast<double>(mLastFrame.timestamp-last_ts)/1e9;
833  // last_ts = mLastFrame.timestamp;
834  // std::cout << "[Video] Frame FPS: " << 1./dT << std::endl;
835 
836 #ifdef SENSORS_MOD_AVAILABLE
837  if(mSensReadyToSync)
838  {
839  mSensReadyToSync = false;
840  mSensPtr->updateTimestampOffset(mLastFrame.timestamp);
841  }
842 #endif
843 
844 #ifdef SENSOR_LOG_AVAILABLE
845  // ----> AEC/AGC register logging
846  if(mLogEnable)
847  {
848  static int frame_count =0;
849 
850 
851  if((++frame_count)==mLogFrameSkip)
852  frame_count = 0;
853 
854  if(frame_count==0)
855  {
856  saveLogDataLeft();
857  saveLogDataRight();
858  }
859  }
860  // <---- AEC/AGC register logging
861 #endif
862 
863  mNewFrame=true;
864  }
865  mBufMutex.unlock();
866 
867  mComMutex.lock();
868  ioctl(mFileDesc, VIDIOC_QBUF, &buf);
869  mComMutex.unlock();
870 
871  capture_frame_count++;
872  }
873  else
874  {
875  if (buf.bytesused != buf.length)
876  {
877  mComMutex.lock();
878  ioctl(mFileDesc, VIDIOC_QBUF, &buf);
879  mComMutex.unlock();
880  }
881  usleep(200);
882  buf.bytesused = -1;
883  buf.length = 0;
884  }
885  }
886 
887  mGrabRunning = false;
888 }
889 
890 const Frame& VideoCapture::getLastFrame( uint64_t timeout_msec )
891 {
892  // ----> Wait for a new frame
893  uint64_t time_count = timeout_msec*10;
894  while( !mNewFrame )
895  {
896  if(time_count==0)
897  {
898  return mLastFrame;
899  }
900  time_count--;
901  usleep(100);
902  }
903  // <---- Wait for a new frame
904 
905  // Get the frame mutex
906  const std::lock_guard<std::mutex> lock(mBufMutex);
907  mNewFrame = false;
908  return mLastFrame;
909 }
910 
911 int VideoCapture::ll_VendorControl(uint8_t *buf, int len, int readMode, bool safe, bool force)
912 {
913  if (len > 384)
914  return -2;
915 
916  if (!force && !mInitialized)
917  return -3;
918 
919  unsigned char tmp[2] = {0};
920  struct uvc_xu_control_query xu_query_info;
921  xu_query_info.unit = cbs_xu_unit_id;
922  xu_query_info.selector = cbs_xu_control_selector;
923  xu_query_info.query = UVC_GET_LEN;
924  xu_query_info.size = 2;
925  xu_query_info.data = tmp;
926 
927  const std::lock_guard<std::mutex> lock(mComMutex);
928 
929  int io_err = ioctl(mFileDesc, UVCIOC_CTRL_QUERY, &xu_query_info);
930 
931  //std::cerr << "[ll_VendorControl] '" << mDevName << "' [" << mDevId << "] - mFileDesc: " << mFileDesc << std::endl;
932 
933  if (io_err != 0)
934  {
935  return -4;
936  }
937  else
938  {
939  len = (xu_query_info.data[1] << 8) + xu_query_info.data[0];
940  }
941 
942  //len should be now 384 for USB3 and 64 for USB2
943  // we use the UVC_SET_CUR to write the cmd
944  struct uvc_xu_control_query xu_query_send;
945  xu_query_send.unit = cbs_xu_unit_id;
946  xu_query_send.selector = cbs_xu_control_selector;
947  xu_query_send.query = UVC_SET_CUR;
948  xu_query_send.size = static_cast<__u16> (len); //64 for USB2
949  xu_query_send.data = buf;
950 
951  io_err = ioctl(mFileDesc, UVCIOC_CTRL_QUERY, &xu_query_send);
952  if (io_err != 0)
953  {
954  int res = errno;
955 
956  const char *err=nullptr;
957  switch (res) {
958  case ENOENT:
959  err = "Extension unit or control not found";
960  break;
961  case ENOBUFS:
962  err = "Buffer size does not match control size";
963  break;
964  case EINVAL:
965  err = "Invalid request code";
966  break;
967  case EBADRQC:
968  err = "Request not supported by control";
969  break;
970  default:
971  err = strerror(res);
972  break;
973  }
974 
975  if(mParams.verbose)
976  {
977  std::string msg = std::string("CBS SET failed") +
978  std::string(err) +
979  std::string(". (System code: ") +
980  std::to_string(res) +
981  std::string(") ") +
982  std::to_string(xu_query_send.size);
983  ERROR_OUT(mParams.verbose,msg);
984  }
985 
986  return -1;
987  }
988 
989 #if 1
990  if (!safe)
991  usleep(300);
992  else
993  usleep(2000);
994 
995  if (readMode == READ_MODE) {
996 
997  struct uvc_xu_control_query xu_query;
998  xu_query.unit = cbs_xu_unit_id,
999  xu_query.selector = cbs_xu_control_selector,
1000  xu_query.query = UVC_GET_CUR,
1001  xu_query.size = static_cast<__u16> (len),
1002  xu_query.data = buf;
1003 
1004  io_err = ioctl(mFileDesc, UVCIOC_CTRL_QUERY, &xu_query);
1005  if (io_err != 0) {
1006  int res = errno;
1007 
1008  const char *err;
1009  switch (res) {
1010  case ENOENT: err = "Extension unit or control not found";
1011  break;
1012  case ENOBUFS: err = "Buffer size does not match control size";
1013  break;
1014  case EINVAL: err = "Invalid request code";
1015  break;
1016  case EBADRQC: err = "Request not supported by control";
1017  break;
1018  default: err = strerror(res);
1019  break;
1020  }
1021 
1022  if(mParams.verbose)
1023  {
1024  std::string msg = std::string("CBS GET failed") +
1025  std::string(err) +
1026  std::string(". (System code: ") +
1027  std::to_string(res) +
1028  std::string(") ") +
1029  std::to_string(xu_query_send.size);
1030  ERROR_OUT(mParams.verbose,msg);
1031  }
1032  return -1;
1033  }
1034 
1035  return 0;
1036  }
1037  else
1038  {
1039  return 0;
1040  }
1041 
1042 #endif
1043 
1044 
1045 }
1046 
1053 int VideoCapture::ll_get_gpio_value(int gpio_number, uint8_t *value)
1054 {
1055  unsigned char xu_buf[384];
1056  memset(xu_buf, 0, 384);
1057 
1058  //Set xubuf
1059  xu_buf[0] = XU_TASK_GET;
1060  xu_buf[1] = 0x13;
1061  xu_buf[2] = gpio_number;
1062 
1063  int hr = ll_VendorControl(xu_buf, 384, 1);
1064  *value = xu_buf[17];
1065  return hr;
1066 }
1067 
1074 int VideoCapture::ll_set_gpio_value(int gpio_number, uint8_t value)
1075 {
1076  unsigned char xu_buf[64];
1077  memset(xu_buf, 0, 64);
1078 
1079  //Set xubuf
1080  xu_buf[0] = XU_TASK_SET;
1081  xu_buf[1] = 0x12;
1082  xu_buf[2] = gpio_number;
1083  xu_buf[3] = value;
1084 
1085  int hr = ll_VendorControl(xu_buf, 64, 0);
1086  return hr;
1087 }
1088 
1095 int VideoCapture::ll_set_gpio_direction(int gpio_number, int direction)
1096 {
1097  unsigned char xu_buf[64];
1098  memset(xu_buf, 0, 64);
1099 
1100  //Set xubuf
1101  xu_buf[0] = XU_TASK_SET;
1102  xu_buf[1] = 0x10;
1103  xu_buf[2] = gpio_number;
1104  xu_buf[3] = direction;
1105 
1106  int hr = ll_VendorControl(xu_buf, 64, 0);
1107  return hr;
1108 }
1109 
1110 int VideoCapture::ll_read_system_register(uint64_t address, uint8_t *value)
1111 {
1112  unsigned char xu_buf[384];
1113  memset(xu_buf, 0, 384);
1114 
1115  //Set xubuf
1116  xu_buf[0] = XU_TASK_GET;
1117  xu_buf[1] = 0xA2;
1118  xu_buf[2] = 0;
1119  xu_buf[3] = 0x04; //Address width in bytes
1120  xu_buf[4] = 0x01; //data width in bytes
1121 
1122  xu_buf[5] = ((address) >> 24) & 0xff;
1123  xu_buf[6] = ((address) >> 16) & 0xff;
1124  xu_buf[7] = ((address) >> 8) & 0xff;
1125  xu_buf[8] = (address) & 0xff;
1126  xu_buf[9] = 0x00;
1127  xu_buf[10] = 0x01;
1128  xu_buf[11] = 0x00;
1129  xu_buf[12] = 0x01;
1130 
1131  int hr = ll_VendorControl(xu_buf, 384, READ_MODE);
1132  *value = xu_buf[17];
1133  return hr;
1134 }
1135 
1136 int VideoCapture::ll_write_system_register(uint64_t address, uint8_t value)
1137 {
1138  unsigned char xu_buf[384];
1139  memset(xu_buf, 0, 384);
1140 
1141  //Set xubuf
1142  xu_buf[0] = XU_TASK_SET;
1143  xu_buf[1] = 0xA2;
1144  xu_buf[2] = 0;
1145  xu_buf[3] = 0x04; //Address width in bytes
1146  xu_buf[4] = 0x01; //data width in bytes
1147 
1148  xu_buf[5] = ((address) >> 24) & 0xff;
1149  xu_buf[6] = ((address) >> 16) & 0xff;
1150  xu_buf[7] = ((address) >> 8) & 0xff;
1151  xu_buf[8] = (address) & 0xff;
1152  xu_buf[9] = 0x00;
1153  xu_buf[10] = 0x01;
1154  xu_buf[11] = 0x00;
1155  xu_buf[12] = 0x01;
1156  xu_buf[16] = value;
1157 
1158  int hr = ll_VendorControl(xu_buf, 384, 0);
1159  return hr;
1160 }
1161 
1162 #define ASIC_INT_NULL_I2C 0xa3
1163 #define ASIC_INT_I2C 0xa5
1164 
1165 int VideoCapture::ll_read_sensor_register(int side, int sscb_id, uint64_t address, uint8_t* value)
1166 {
1167  unsigned char xu_buf[384];
1168  memset(xu_buf, 0, 384);
1169 
1170 
1171  //Set xubuf
1172  xu_buf[0] = XU_TASK_GET;
1173  if (side == 0)
1174  xu_buf[1] = ASIC_INT_NULL_I2C;
1175  else
1176  xu_buf[1] = ASIC_INT_I2C;
1177  xu_buf[2] = 0x6c;
1178  xu_buf[3] = sscb_id + 1; //Address width in bytes
1179  xu_buf[4] = 0x01; //data width in bytes
1180 
1181  xu_buf[5] = ((address) >> 24) & 0xff;
1182  xu_buf[6] = ((address) >> 16) & 0xff;
1183  xu_buf[7] = ((address) >> 8) & 0xff;
1184  xu_buf[8] = (address) & 0xff;
1185 
1186  xu_buf[9] = 0x00;
1187  xu_buf[10] = 0x01;
1188  xu_buf[11] = 0x00;
1189  xu_buf[12] = 0x01;
1190 
1191  int limit = 1;
1192 
1193  xu_buf[9] = (limit >> 8) & 0xff;
1194  xu_buf[10] = (limit >> 0) & 0xff;
1195 
1196  //set page addr
1197  xu_buf[9] = xu_buf[9] & 0x0f;
1198  xu_buf[9] = xu_buf[9] | 0x10;
1199  xu_buf[9] = xu_buf[9] | 0x80;
1200 
1201  int hr = ll_VendorControl(xu_buf, 384, READ_MODE);
1202  *value = xu_buf[17];
1203  return hr;
1204 }
1205 
1206 int VideoCapture::ll_write_sensor_register(int side, int sscb_id, uint64_t address, uint8_t value)
1207 {
1208 
1209  unsigned char xu_buf[384];
1210  memset(xu_buf, 0, 384);
1211 
1212  //Set xubuf
1213  xu_buf[0] = XU_TASK_SET;
1214  if (side == 0)
1215  xu_buf[1] = ASIC_INT_NULL_I2C;
1216  else
1217  xu_buf[1] = ASIC_INT_I2C;
1218  xu_buf[2] = 0x6c;
1219  xu_buf[3] = sscb_id + 1; //Address width in bytes
1220  xu_buf[4] = 0x01; //data width in bytes
1221 
1222  xu_buf[5] = ((address) >> 24) & 0xff;
1223  xu_buf[6] = ((address) >> 16) & 0xff;
1224  xu_buf[7] = ((address) >> 8) & 0xff;
1225  xu_buf[8] = (address) & 0xff;
1226  xu_buf[9] = 0x00;
1227  xu_buf[10] = 0x01;
1228  xu_buf[11] = 0x00;
1229  xu_buf[12] = 0x01;
1230  xu_buf[16] = value;
1231 
1232 
1233  xu_buf[9] = 0x00;
1234  xu_buf[10] = 0x01;
1235  xu_buf[11] = 0x00;
1236  xu_buf[12] = 0x01;
1237 
1238  int limit = 1;
1239  xu_buf[9] = (limit >> 8) & 0xff;
1240  xu_buf[10] = (limit >> 0) & 0xff;
1241 
1242  //set page addr
1243  xu_buf[9] = xu_buf[9] & 0x0f;
1244  xu_buf[9] = xu_buf[9] | 0x10;
1245  xu_buf[9] = xu_buf[9] | 0x80;
1246  memcpy(&xu_buf[16], &value, sizeof (uint8_t));
1247  int hr = ll_VendorControl(xu_buf, 384, 0);
1248 
1249  return hr;
1250 }
1251 
1252 int VideoCapture::ll_SPI_FlashProgramRead(uint8_t *pBuf, int Adr, int len, bool force) {
1253 
1254  int hr = -1;
1255  uint8_t xu_buf[384];
1256  memset(xu_buf, 0, 384);
1257 
1258  xu_buf[0] = 0x51;
1259  xu_buf[1] = 0xA1;
1260  xu_buf[2] = 0x03;
1261 
1262  xu_buf[5] = (Adr >> 24) & 0xff;
1263  xu_buf[6] = (Adr >> 16) & 0xff;
1264  xu_buf[7] = (Adr >> 8) & 0xff;
1265  xu_buf[8] = (Adr) & 0xff;
1266 
1267  int pack_val = 36864 + len;
1268  xu_buf[9] = ((pack_val) >> 8) & 0xff;
1269  xu_buf[10] = ((pack_val) >> 0) & 0xff;
1270 
1271  xu_buf[11] = ((len) >> 8) & 0xff;
1272  xu_buf[12] = ((len) >> 0) & 0xff;
1273 
1274  hr = ll_VendorControl(xu_buf, len, 1, true, force);
1275  memcpy(pBuf, &xu_buf[17], len);
1276  return hr;
1277 }
1278 
1279 int VideoCapture::ll_isp_aecagc_enable(int side, bool enable) {
1280  uint64_t Address = 0;
1281  uint8_t value = 0;
1282  int hr = 0;
1283  if (side == 0)
1284  Address = ISP_CTRL_LEFT; //ISP L
1285  else if (side == 1)
1286  Address = ISP_CTRL_RIGHT; //ISP R
1287  else
1288  return -2;
1289 
1290  //Read Current sysregister
1291  hr += ll_read_system_register(Address, &value);
1292 
1293  // Adjust Value
1294  if (enable)
1295  value = value | AEG_AGC_MASK_ON;
1296  else
1297  value = value & AEG_AGC_MASK_OFF;
1298 
1299  hr += ll_write_system_register(Address, value);
1300 
1301  return hr;
1302 }
1303 
1304 
1305 int VideoCapture::ll_isp_is_aecagc(int side) {
1306  uint64_t Address = 0;
1307  uint8_t value = 0;
1308  int result = 0;
1309  int hr = 0;
1310  if (side == 0)
1311  Address = ISP_CTRL_LEFT; //ISP L
1312  else if (side == 1)
1313  Address = ISP_CTRL_RIGHT; //ISP R
1314  else
1315  return -2;
1316 
1317  //Read Current sysregister
1318  hr += ll_read_system_register(Address, &value);
1319 
1320  // Adjust Value
1321  if (hr == 0)
1322  result = ((value & AEG_AGC_MASK_ON) == AEG_AGC_MASK_ON); //check that second bit is on
1323  else
1324  return hr;
1325 
1326  return result;
1327 }
1328 
1329 int VideoCapture::ll_isp_get_gain(uint8_t *val, uint8_t sensorID) {
1330  int hr = 0;
1331  uint8_t buffL, buffM, buffH;
1332 
1333  hr += ll_read_sensor_register(sensorID, 1, ADDR_GAIN_H, &buffH);
1334  hr += ll_read_sensor_register(sensorID, 1, ADDR_GAIN_M, &buffM);
1335  hr += ll_read_sensor_register(sensorID, 1, ADDR_GAIN_L, &buffL);
1336 
1337  *val = buffL;
1338  *(val + 1) = buffM;
1339  *(val + 2) = buffH;
1340 
1341  return hr;
1342 }
1343 
1344 int VideoCapture::ll_isp_set_gain(unsigned char ucGainH, unsigned char ucGainM, unsigned char ucGainL, int sensorID)
1345 {
1346  int hr = 0;
1347  hr += ll_write_sensor_register(sensorID, 1, ADDR_GAIN_H, ucGainH);
1348  hr += ll_write_sensor_register(sensorID, 1, ADDR_GAIN_M, ucGainM);
1349  hr += ll_write_sensor_register(sensorID, 1, ADDR_GAIN_L, ucGainL);
1350  return hr;
1351 }
1352 
1353 int VideoCapture::ll_isp_get_exposure(unsigned char *val, unsigned char sensorID)
1354 {
1355  int hr = 0;
1356  uint8_t buffL = 0;
1357  uint8_t buffM = 0;
1358  uint8_t buffH = 0;
1359 
1360  hr += ll_read_sensor_register(sensorID, 1, ADDR_EXP_H, (uint8_t*) & buffH);
1361  usleep(10);
1362  hr += ll_read_sensor_register(sensorID, 1, ADDR_EXP_M, (uint8_t*) & buffM);
1363  usleep(10);
1364  hr += ll_read_sensor_register(sensorID, 1, ADDR_EXP_L, (uint8_t*) & buffL);
1365 
1366  *val = buffL;
1367  *(val + 1) = buffM;
1368  *(val + 2) = buffH;
1369 
1370  return hr;
1371 }
1372 
1373 int VideoCapture::ll_isp_set_exposure(unsigned char ucExpH, unsigned char ucExpM, unsigned char ucExpL, int sensorID)
1374 {
1375  int hr = 0;
1376  hr += ll_write_sensor_register(sensorID, 1, ADDR_EXP_H, ucExpH);
1377  hr += ll_write_sensor_register(sensorID, 1, ADDR_EXP_M, ucExpM);
1378  hr += ll_write_sensor_register(sensorID, 1, ADDR_EXP_L, ucExpL);
1379  return hr;
1380 }
1381 
1382 void VideoCapture::ll_activate_sync()
1383 {
1384  uint8_t sync_val_left = 0x0;
1385  uint8_t sync_val_right = 0x0;
1386 
1387  // Activate VSYNC output for both camera sensors
1388  if (ll_read_sensor_register(0, 1, 0x3002, &sync_val_left) == 0)
1389  {
1390  sync_val_left = sync_val_left | 0x80;
1391 
1392  ll_write_sensor_register(0, 1, 0x3002, sync_val_left);
1393  }
1394 
1395  if (ll_read_sensor_register(1, 1, 0x3002, &sync_val_right) == 0)
1396  {
1397  sync_val_right = sync_val_right | 0x80;
1398 
1399  ll_write_sensor_register(1, 1, 0x3002, sync_val_right);
1400  }
1401 }
1402 
1404 {
1405  int hr = 0;
1406  //LED GPIO : GPIO 2
1407  if (status) {
1408  hr += ll_set_gpio_direction(2, 0);
1409  hr += ll_set_gpio_value(2, 1);
1410  } else {
1411  hr += ll_set_gpio_direction(2, 0);
1412  hr += ll_set_gpio_value(2, 0);
1413  }
1414 
1415  return hr;
1416 }
1417 
1419 {
1420  if( status==nullptr)
1421  {
1422  return -1;
1423  }
1424 
1425  uint8_t val;
1426  int hr = ll_set_gpio_direction(2, 1);
1427  hr += ll_get_gpio_value(2, &val);
1428  *status = val!=0;
1429  return hr;
1430 }
1431 
1432 int VideoCapture::toggleLED(bool* value)
1433 {
1434  bool curVal;
1435 
1436  int ret = getLEDstatus( &curVal );
1437 
1438  if(ret==0)
1439  {
1440  bool newVal = !curVal;
1441  ret = setLEDstatus( newVal );
1442 
1443  if( ret==0 && value!=nullptr )
1444  {
1445  *value = newVal;
1446  }
1447  }
1448 
1449  return ret;
1450 }
1451 
1452 int VideoCapture::getCameraControlSettings(int ctrl_id)
1453 {
1454  struct v4l2_control control_s;
1455  struct v4l2_queryctrl queryctrl;
1456  memset(&queryctrl, 0, sizeof (queryctrl));
1457  memset(&control_s, 0, sizeof (control_s));
1458  int res = -1;
1459 
1460  // save_controls(fd);
1461  queryctrl.id = ctrl_id;
1462 
1463  if (0 != ioctl(mFileDesc, VIDIOC_QUERYCTRL, &queryctrl))
1464  return res;
1465 
1466  control_s.id = ctrl_id;
1467  if (ioctl(mFileDesc, VIDIOC_G_CTRL, &control_s) == 0)
1468  res = (int) control_s.value;
1469 
1470  return res;
1471 }
1472 
1473 void VideoCapture::setCameraControlSettings(int ctrl_id, int ctrl_val) {
1474  struct v4l2_control control_s;
1475  struct v4l2_queryctrl queryctrl;
1476  memset(&queryctrl, 0, sizeof (queryctrl));
1477  memset(&control_s, 0, sizeof (control_s));
1478  int min, max/*, step, val_def*/;
1479 
1480  // save_controls(fd);
1481  queryctrl.id = ctrl_id;
1482 
1483  //std::cerr << "[setCameraControlSettings] '" << mDevName << "' [" << mDevId << "] - mFileDesc: " << mFileDesc << std::endl;
1484 
1485  int res = ioctl(mFileDesc, VIDIOC_QUERYCTRL, &queryctrl);
1486  if (0 == res) {
1487  min = queryctrl.minimum;
1488  max = queryctrl.maximum;
1489  //step = queryctrl.step;
1490  //val_def = queryctrl.default_value;
1491 
1492  if (ctrl_id == LINUX_CTRL_GAMMA) {
1493  min = DEFAULT_MIN_GAMMA;
1494  max = DEFAULT_MAX_GAMMA;
1495  }
1496 
1497  } else {
1498  min = 0; // queryctrl.minimum;
1499  max = 6500; // queryctrl.maximum;
1500  //step = queryctrl.step;
1501  //val_def = queryctrl.default_value;
1502  }
1503 
1504  if ((ctrl_val >= min) && (ctrl_val <= max)) {
1505  control_s.id = ctrl_id;
1506  control_s.value = ctrl_val;
1507 
1508 
1509  if (ioctl(mFileDesc, VIDIOC_S_CTRL, &control_s) == 0)
1510  return;
1511  } else
1512  return;
1513 }
1514 
1515 void VideoCapture::resetCameraControlSettings(int ctrl_id) {
1516 
1517  struct v4l2_control control_s;
1518  struct v4l2_queryctrl queryctrl;
1519  memset(&queryctrl, 0, sizeof (queryctrl));
1520  memset(&control_s, 0, sizeof (control_s));
1521  int val_def;
1522  // save_controls(fd);
1523  queryctrl.id = ctrl_id;
1524  ioctl(mFileDesc, VIDIOC_QUERYCTRL, &queryctrl);
1525  val_def = queryctrl.default_value;
1526 
1527  control_s.id = ctrl_id;
1528  control_s.value = val_def;
1529  ioctl(mFileDesc, VIDIOC_S_CTRL, &control_s);
1530  return;
1531 }
1532 
1533 int VideoCapture::setGammaPreset(int side, int value)
1534 {
1535  if (!mInitialized)
1536  return -1;
1537 
1538  if(value < DEFAULT_MIN_GAMMA)
1539  value = DEFAULT_MIN_GAMMA;
1540  if(value > DEFAULT_MAX_GAMMA)
1541  value = DEFAULT_MAX_GAMMA;
1542 
1543  uint64_t ulAddr = 0x80181500;
1544 
1545  if (side == 1)
1546  ulAddr = 0x80181D00;
1547 
1548  int hr = 0;
1549 
1550  for (int i = 0; i < 15; i++) {
1551  hr += ll_write_system_register(ulAddr, PRESET_GAMMA[value-1][i]);
1552  usleep(10);
1553  uint8_t valRead = 0x0;
1554  hr += ll_read_system_register(ulAddr, &valRead);
1555  if (valRead != PRESET_GAMMA[value-1][i]) {
1556  return -3;
1557  }
1558  ulAddr++;
1559  }
1560 
1561  ulAddr = 0x80181510;
1562 
1563  if (side == 1)
1564  ulAddr = 0x80181D10;
1565  hr += ll_write_system_register(ulAddr, 0x01);
1566  usleep(10);
1567  uint8_t valRead = 0x0;
1568  hr += ll_read_system_register(ulAddr, &valRead);
1569  if (valRead != 0x01)
1570  return -2;
1571 
1572  return hr;
1573 }
1574 
1575 void VideoCapture::setBrightness(int brightness)
1576 {
1577  setCameraControlSettings(LINUX_CTRL_BRIGHTNESS, brightness);
1578 }
1579 
1581 {
1582  resetCameraControlSettings(LINUX_CTRL_BRIGHTNESS);
1583 }
1584 
1586 {
1587  return getCameraControlSettings(LINUX_CTRL_BRIGHTNESS);
1588 }
1589 
1590 void VideoCapture::setSharpness(int sharpness)
1591 {
1592  setCameraControlSettings(LINUX_CTRL_SHARPNESS, sharpness);
1593 }
1594 
1596 {
1597  resetCameraControlSettings(LINUX_CTRL_SHARPNESS);
1598 }
1599 
1601 {
1602  return getCameraControlSettings(LINUX_CTRL_SHARPNESS);
1603 }
1604 
1605 void VideoCapture::setContrast(int contrast)
1606 {
1607  setCameraControlSettings(LINUX_CTRL_CONTRAST, contrast);
1608 }
1609 
1611 {
1612  resetCameraControlSettings(LINUX_CTRL_CONTRAST);
1613 }
1614 
1616 {
1617  return getCameraControlSettings(LINUX_CTRL_CONTRAST);
1618 }
1619 
1621 {
1622  setCameraControlSettings(LINUX_CTRL_HUE, hue);
1623 }
1624 
1626 {
1627  resetCameraControlSettings(LINUX_CTRL_HUE);
1628 }
1629 
1631 {
1632  return getCameraControlSettings(LINUX_CTRL_HUE);
1633 }
1634 
1635 void VideoCapture::setSaturation(int saturation)
1636 {
1637  setCameraControlSettings(LINUX_CTRL_SATURATION, saturation);
1638 }
1639 
1641 {
1642  resetCameraControlSettings(LINUX_CTRL_SATURATION);
1643 }
1644 
1646 {
1647  return getCameraControlSettings(LINUX_CTRL_SATURATION);
1648 }
1649 
1651 {
1652  return getCameraControlSettings(LINUX_CTRL_AWB);
1653 }
1654 
1656 {
1657  // Disable auto white balance if active
1658  if (getAutoWhiteBalance() != 0)
1659  setAutoWhiteBalance(false);
1660 
1661  setCameraControlSettings(LINUX_CTRL_AWB, wb);
1662 }
1663 
1665 {
1666  return (getCameraControlSettings(LINUX_CTRL_AWB_AUTO)!=0);
1667 }
1668 
1670 {
1671  setCameraControlSettings(LINUX_CTRL_AWB_AUTO, active?1:0);
1672 }
1673 
1675 {
1676  setAutoWhiteBalance(true);
1677 }
1678 
1679 void VideoCapture::setGamma(int gamma)
1680 {
1681  int current_gamma = getCameraControlSettings(LINUX_CTRL_GAMMA);
1682 
1683  if (gamma!=current_gamma)
1684  {
1685  setGammaPreset(0,gamma);
1686  setGammaPreset(1,gamma);
1687  setCameraControlSettings(LINUX_CTRL_GAMMA, gamma);
1688  }
1689 }
1690 
1692 {
1693  int def_value = DEFAULT_GAMMA_NOECT;
1694  setGammaPreset(0,def_value);
1695  setGammaPreset(1,def_value);
1696  setCameraControlSettings(LINUX_CTRL_GAMMA, def_value);
1697 }
1698 
1700  return getCameraControlSettings(LINUX_CTRL_GAMMA);
1701 }
1702 
1703 int VideoCapture::setAECAGC(bool active)
1704 {
1705  int res = 0;
1706  res += ll_isp_aecagc_enable(0, active);
1707  res += ll_isp_aecagc_enable(1, active);
1708  return res;
1709 }
1710 
1712 {
1713  int resL = ll_isp_is_aecagc(0);
1714  int resR = ll_isp_is_aecagc(1);
1715  return (resL && resR);
1716 }
1717 
1719 {
1720  setAECAGC(true);
1721 }
1722 
1723 bool VideoCapture::setROIforAECAGC(CAM_SENS_POS side, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
1724 {
1725  if(side!=CAM_SENS_POS::LEFT && side!=CAM_SENS_POS::RIGHT)
1726  {
1727  return false;
1728  }
1729  if(w==0 || h==0)
1730  {
1731  return false;
1732  }
1733  if((x+w)>(mWidth/2) || (y+h)>mHeight)
1734  {
1735  return false;
1736  }
1737  if(w*h<=100)
1738  {
1739  return false;
1740  }
1741 
1742  int x_start_high = x / 256;
1743  int x_start_low = (x - x_start_high * 256);
1744  int y_start_high = y / 256;
1745  int y_start_low = (y - x_start_high * 256);
1746  int w_start_high = w / 256;
1747  int w_start_low = (w - x_start_high * 256);
1748  int h_start_high = h / 256;
1749  int h_start_low = (h - x_start_high * 256);
1750 
1751 
1752  uint32_t ulAddr = 0x801810C0;
1753  if (static_cast<int>(side)==1)
1754  ulAddr= 0x801818C0;
1755 
1756  int r = ll_write_system_register(ulAddr,static_cast<uint8_t>(x_start_high));ulAddr++;usleep(100);
1757  r += ll_write_system_register(ulAddr,static_cast<uint8_t>(x_start_low));ulAddr++;usleep(100);
1758  r += ll_write_system_register(ulAddr,static_cast<uint8_t>(y_start_high));ulAddr++;usleep(100);
1759  r += ll_write_system_register(ulAddr,static_cast<uint8_t>(y_start_low));ulAddr++;usleep(100);
1760  r += ll_write_system_register(ulAddr,static_cast<uint8_t>(w_start_high));ulAddr++;usleep(100);
1761  r += ll_write_system_register(ulAddr,static_cast<uint8_t>(w_start_low));ulAddr++;usleep(100);
1762  r += ll_write_system_register(ulAddr,static_cast<uint8_t>(h_start_high));ulAddr++;usleep(100);
1763  r += ll_write_system_register(ulAddr,static_cast<uint8_t>(h_start_low));ulAddr++;usleep(100);
1764 
1765  return (r==0);
1766 }
1767 
1769 {
1770  return setROIforAECAGC(side, 0,0, mWidth/2, mHeight);
1771 }
1772 
1773 bool VideoCapture::getROIforAECAGC(CAM_SENS_POS side, uint16_t &x, uint16_t &y, uint16_t &w, uint16_t &h)
1774 {
1775  uint8_t x_start_high = 0;
1776  uint8_t x_start_low = 0;
1777  uint8_t y_start_high =0;
1778  uint8_t y_start_low = 0;
1779  uint8_t w_start_high =0;
1780  uint8_t w_start_low = 0;
1781  uint8_t h_start_high = 0;
1782  uint8_t h_start_low = 0;
1783  uint32_t ulAddr = 0x801810C0;
1784  if (static_cast<int>(side)==1)
1785  ulAddr= 0x801818C0;
1786  int r = ll_read_system_register(ulAddr,&x_start_high);ulAddr++;usleep(100);
1787  r += ll_read_system_register(ulAddr,&x_start_low);ulAddr++;usleep(100);
1788  r += ll_read_system_register(ulAddr,&y_start_high);ulAddr++;usleep(100);
1789  r += ll_read_system_register(ulAddr,&y_start_low);ulAddr++;usleep(100);
1790  r += ll_read_system_register(ulAddr,&w_start_high);ulAddr++;usleep(100);
1791  r += ll_read_system_register(ulAddr,&w_start_low);ulAddr++;usleep(100);
1792  r += ll_read_system_register(ulAddr,&h_start_high);ulAddr++;usleep(100);
1793  r += ll_read_system_register(ulAddr,&h_start_low);ulAddr++;usleep(100);
1794 
1795  x = x_start_high*256 + x_start_low;
1796  y = y_start_high*256 + y_start_low;
1797  w = w_start_high*256 + w_start_low;
1798  h = h_start_high*256 + h_start_low;
1799 
1800  return (r==0);
1801 }
1802 
1804 {
1805  if(getAECAGC())
1806  setAECAGC(false);
1807 
1808  if (gain <= DEFAULT_MIN_GAIN)
1809  gain = DEFAULT_MIN_GAIN;
1810  else if (gain >= DEFAULT_MAX_GAIN)
1811  gain = DEFAULT_MAX_GAIN;
1812 
1813  uint8_t ucGainH=0, ucGainM=0, ucGainL=0;
1814 
1815  int rawGain = calcRawGainValue(gain);
1816 
1817  int sensorId = static_cast<int>(cam);
1818 
1819  ucGainM = (rawGain >> 8) & 0xff;
1820  ucGainL = rawGain & 0xff;
1821  ll_isp_set_gain(ucGainH, ucGainM, ucGainL, sensorId);
1822 
1823 }
1824 
1826 {
1827  int rawGain=0;
1828 
1829  uint8_t val[3];
1830  memset(val, 0, 3);
1831 
1832  int sensorId = static_cast<int>(cam);
1833  int r = ll_isp_get_gain(val, sensorId);
1834  if(r<0)
1835  return r;
1836 
1837  rawGain = (int) ((val[1] << 8) + val[0]);
1838  return calcGainValue(rawGain);
1839 }
1840 
1842 {
1843  unsigned char ucExpH, ucExpM, ucExpL;
1844 
1845  if(getAECAGC())
1846  setAECAGC(false);
1847 
1848  if(exposure < DEFAULT_MIN_EXP)
1849  exposure = DEFAULT_MIN_EXP;
1850  if(exposure > DEFAULT_MAX_EXP)
1851  exposure = DEFAULT_MAX_EXP;
1852 
1853  int rawExp = (mExpoureRawMax * ((float) exposure / 100.0));
1854  if(rawExp<EXP_RAW_MIN)
1855  rawExp = EXP_RAW_MIN;
1856 
1857  //std::cout << "Set Raw Exp: " << rawExp << std::endl;
1858 
1859  int sensorId = static_cast<int>(cam);
1860 
1861  ucExpH = (rawExp >> 12) & 0xff;
1862  ucExpM = (rawExp >> 4) & 0xff;
1863  ucExpL = (rawExp << 4) & 0xf0;
1864  ll_isp_set_exposure(ucExpH, ucExpM, ucExpL, sensorId);
1865 }
1866 
1868 {
1869  int rawExp=0;
1870 
1871  unsigned char val[3];
1872  memset(val, 0, 3);
1873 
1874  int sensorId = static_cast<int>(cam);
1875 
1876  int r = ll_isp_get_exposure(val, sensorId);
1877  if(r<0)
1878  return r;
1879  rawExp = (int) ((val[2] << 12) + (val[1] << 4) + (val[0] >> 4));
1880 
1881  //std::cout << "Get Raw Exp: " << rawExp << std::endl;
1882 
1883  int exposure = static_cast<int>(std::round((100.0*rawExp)/mExpoureRawMax));
1884  return exposure;
1885 }
1886 
1887 int VideoCapture::calcRawGainValue(int gain) {
1888 
1889  // From [0,100] to segmented gain
1890  int segmentedGain = static_cast<int>(std::round(mGainSegMax * (static_cast<double>(gain) / 100.0)));
1891  int rawGain = 0;
1892 
1893  // ----> Calculate correct GAIN ZONE
1894  int gainZone1nbVal = GAIN_ZONE1_MAX - GAIN_ZONE1_MIN;
1895  int gainZone2nbVal = GAIN_ZONE2_MAX - GAIN_ZONE2_MIN;
1896  int gainZone3nbVal = GAIN_ZONE3_MAX - GAIN_ZONE3_MIN;
1897  int gainZone4nbVal = GAIN_ZONE4_MAX - GAIN_ZONE4_MIN;
1898 
1899  if (segmentedGain <= gainZone1nbVal)
1900  rawGain = segmentedGain + GAIN_ZONE1_MIN;
1901  else if (segmentedGain <= gainZone1nbVal + gainZone2nbVal)
1902  rawGain = segmentedGain + GAIN_ZONE2_MIN - (gainZone1nbVal);
1903  else if (segmentedGain <= gainZone1nbVal + gainZone2nbVal + gainZone3nbVal)
1904  rawGain = segmentedGain + GAIN_ZONE3_MIN - (gainZone1nbVal + gainZone2nbVal);
1905  else if (segmentedGain <= gainZone1nbVal + gainZone2nbVal + gainZone3nbVal + gainZone4nbVal)
1906  rawGain = segmentedGain + GAIN_ZONE4_MIN - (gainZone1nbVal + gainZone2nbVal + gainZone3nbVal);
1907  // <---- Calculate correct GAIN ZONE
1908 
1909  return rawGain;
1910 }
1911 
1912 int VideoCapture::calcGainValue(int rawGain)
1913 {
1914  int segmentedGain;
1915 
1916  // ----> Calculate correct GAIN ZONE
1917  int gainZone1nbVal = GAIN_ZONE1_MAX - GAIN_ZONE1_MIN;
1918  int gainZone2nbVal = GAIN_ZONE2_MAX - GAIN_ZONE2_MIN;
1919  int gainZone3nbVal = GAIN_ZONE3_MAX - GAIN_ZONE3_MIN;
1920  if (rawGain >= GAIN_ZONE1_MIN && rawGain <= GAIN_ZONE1_MAX)
1921  segmentedGain = rawGain - GAIN_ZONE1_MIN;
1922  else if (rawGain >= GAIN_ZONE2_MIN && rawGain <= GAIN_ZONE2_MAX)
1923  segmentedGain = rawGain - GAIN_ZONE2_MIN + gainZone1nbVal;
1924  else if (rawGain >= GAIN_ZONE3_MIN && rawGain <= GAIN_ZONE3_MAX)
1925  segmentedGain = rawGain - GAIN_ZONE3_MIN + gainZone1nbVal + gainZone2nbVal;
1926  else if (rawGain >= GAIN_ZONE4_MIN && rawGain <= GAIN_ZONE4_MAX)
1927  segmentedGain = rawGain - GAIN_ZONE4_MIN + gainZone1nbVal + gainZone2nbVal + gainZone3nbVal;
1928  else
1929  segmentedGain = -1;
1930  // <---- Calculate correct GAIN ZONE
1931 
1932  // From segmented gain to [0,100]
1933  int gain = static_cast<int>(std::round((100.0*segmentedGain)/mGainSegMax));
1934 
1935  return gain;
1936 }
1937 
1938 #ifdef SENSOR_LOG_AVAILABLE
1939 bool VideoCapture::enableAecAgcSensLogging(bool enable, int frame_skip/*=10*/)
1940 {
1941  if(!enable)
1942  {
1943  mLogEnable=false;
1944  if(mLogFileLeft.is_open())
1945  {
1946  mLogFileLeft.close();
1947  }
1948  if(mLogFileRight.is_open())
1949  {
1950  mLogFileRight.close();
1951  }
1952  return true;
1953  }
1954 
1955  mLogFrameSkip = frame_skip;
1956 
1957  mLogFilenameLeft = getCurrentDateTime(DATE);
1958  mLogFilenameLeft += "_";
1959  mLogFilenameLeft += getCurrentDateTime(TIME);
1960  mLogFilenameLeft += "_agc_aec_registers-LEFT.csv";
1961 
1962  mLogFilenameRight = getCurrentDateTime(DATE);
1963  mLogFilenameRight += "_";
1964  mLogFilenameRight += getCurrentDateTime(TIME);
1965  mLogFilenameRight += "_agc_aec_registers-RIGHT.csv";
1966 
1967  mLogFileLeft.open(mLogFilenameLeft, std::ofstream::out );
1968  mLogFileRight.open(mLogFilenameRight, std::ofstream::out );
1969 
1970  if(mLogFileLeft.bad())
1971  {
1972  std::cerr << "Logging not started. Error creating the log file: '" << mLogFilenameLeft << "'" << std::endl;
1973  mLogEnable = false;
1974  return false;
1975  }
1976 
1977  if(mLogFileRight.bad())
1978  {
1979  std::cerr << "Logging not started. Error creating the log file: '" << mLogFilenameRight << "'" << std::endl;
1980  mLogEnable = false;
1981  mLogFileLeft.close();
1982  return false;
1983  }
1984 
1985  mLogFileLeft << "TIMESTAMP" << LOG_SEP;
1986  mLogFileLeft << "OV580-ISP_EN_HIGH" << LOG_SEP;
1987  mLogFileLeft << "OV580-yavg_low" << LOG_SEP;
1988  mLogFileLeft << "OV580-yavg_high" << LOG_SEP;
1989  mLogFileLeft << "OV580-interrupt_ctrl1";
1990 
1991  mLogFileRight << "TIMESTAMP" << LOG_SEP;
1992  mLogFileRight << "OV580-ISP_EN_HIGH" << LOG_SEP;
1993  mLogFileRight << "OV580-yavg_low" << LOG_SEP;
1994  mLogFileRight << "OV580-yavg_high" << LOG_SEP;
1995  mLogFileRight << "OV580-interrupt_ctrl1";
1996 
1997  for (int addr = 0x00; addr <= 0x22; ++addr)
1998  {
1999  mLogFileLeft << LOG_SEP << "OV580-YAVG[0x" << std::hex << std::setfill('0') << std::setw(2) << addr << "]";
2000  mLogFileRight << LOG_SEP << "OV580-YAVG[0x" << std::hex << std::setfill('0') << std::setw(2) << addr << "]";
2001  }
2002 
2003  for (int addr = 0x3500; addr <= 0x3515; ++addr)
2004  {
2005  mLogFileLeft << LOG_SEP << "OV4689-GAIN_EXP[0x" << std::hex << std::setfill('0') << std::setw(4) << addr << "]";
2006  mLogFileRight << LOG_SEP << "OV4689-GAIN_EXP[0x" << std::hex << std::setfill('0') << std::setw(4) << addr << "]";
2007  }
2008 
2009  mLogFileLeft << std::endl;
2010  mLogFileRight << std::endl;
2011 
2012  mLogEnable = true;
2013  return true;
2014 }
2015 
2016 void VideoCapture::setColorBars(int side, bool c)
2017 {
2018 
2019 
2020  unsigned long long ulAddr2 = 0x80181080;
2021 
2022  if (side==1)
2023  ulAddr2 = 0x80181880;
2024 
2025  unsigned char ulValue2 =c?128:0;
2026  ll_write_system_register(ulAddr2,ulValue2);
2027 }
2028 
2029 
2030 void VideoCapture::saveAllISPRegisters(std::string filename)
2031 {
2032  std::ofstream logFile;
2033  logFile.open(filename,std::ofstream::out);
2034  int res = 0;
2035  unsigned long long ulAddrL = 0x80181000;
2036  unsigned long long ulAddrR = 0x80181800;
2037 
2038  for (int p = 0;p<0x800;p++)
2039  {
2040  uint8_t valL,valR;
2041  res += ll_read_system_register( ulAddrL+p, &valL);
2042  res += ll_read_system_register( ulAddrR+p, &valR);
2043 
2044  logFile <<"0x" << std::hex << std::setfill('0') << std::setw(8) << static_cast<unsigned long long>(ulAddrL+p)<<" , "<<std::hex << std::setfill('0') << std::setw(2) << static_cast<unsigned long long>(valL)<<" , "<<std::hex << std::setfill('0') << std::setw(2) << static_cast<unsigned long long>(valR)<<std::endl;
2045  usleep(10);
2046  }
2047 
2048  logFile.close();
2049 }
2050 
2051 void VideoCapture::saveAllSensorsRegisters(std::string filename)
2052 {
2053  std::ofstream logFile;
2054  logFile.open(filename,std::ofstream::out);
2055 
2056  int res = 0;
2057  for (int addr = 0x3000; addr <= 0x6000; ++addr)
2058  {
2059  uint8_t valL,valR;
2060  res += ll_read_sensor_register( 0, 1, addr, &valL);
2061  res += ll_read_sensor_register( 1, 1, addr, &valR);
2062 
2063  usleep(10);
2064  logFile <<"0x" << std::hex << std::setfill('0') << std::setw(8) << static_cast<int>(addr)<<" , "<<std::hex << std::setfill('0') << std::setw(2) << static_cast<unsigned long long>(valL)<<" , "<<std::hex << std::setfill('0') << std::setw(2) << static_cast<unsigned long long>(valR)<<std::endl;
2065  }
2066 
2067  logFile.close();
2068 }
2069 
2070 void VideoCapture::saveLogDataLeft()
2071 {
2072  const int reg_count = 61;
2073  uint8_t values[reg_count];
2074  int idx = 0;
2075 
2076  int res = 0;
2077  res += ll_read_system_register( 0x80181002, &values[idx++]);
2078  res += ll_read_system_register( 0x80181031, &values[idx++]);
2079  res += ll_read_system_register( 0x80181032, &values[idx++]);
2080  res += ll_read_system_register( 0x80181033, &values[idx++]);
2081 
2082  for(int reg_addr = 0x00; reg_addr <= 0x22; ++reg_addr)
2083  {
2084  uint64_t addr = 0x801810C0+reg_addr;
2085  res += ll_read_system_register( addr, &values[idx++]);
2086  }
2087 
2088  for (int addr = 0x3500; addr <= 0x3515; ++addr)
2089  {
2090  res += ll_read_sensor_register( 0, 1, addr, &values[idx++]);
2091  }
2092 
2093  mLogFileLeft << std::dec << mLastFrame.timestamp << LOG_SEP;
2094  for(int i=0; i<reg_count; i++)
2095  {
2096  mLogFileLeft << "0x" << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(values[i]);
2097  if(i==(reg_count-1))
2098  mLogFileLeft << std::endl;
2099  else
2100  mLogFileLeft << LOG_SEP;
2101  }
2102 }
2103 
2104 void VideoCapture::saveLogDataRight()
2105 {
2106  const int reg_count = 61;
2107  uint8_t values[reg_count];
2108  int idx = 0;
2109 
2110  int res = 0;
2111  res += ll_read_system_register( 0x80181802, &values[idx++]);
2112  res += ll_read_system_register( 0x80181831, &values[idx++]);
2113  res += ll_read_system_register( 0x80181832, &values[idx++]);
2114  res += ll_read_system_register( 0x80181833, &values[idx++]);
2115 
2116  for(int reg_addr = 0x00; reg_addr <= 0x22; ++reg_addr)
2117  {
2118  uint64_t addr = 0x801818C0+reg_addr;
2119  res += ll_read_system_register( addr, &values[idx++]);
2120  }
2121 
2122  for (int addr = 0x3500; addr <= 0x3515; ++addr)
2123  {
2124  res += ll_read_sensor_register( 1, 1, addr, &values[idx++]);
2125  }
2126 
2127  mLogFileRight << std::dec << mLastFrame.timestamp << LOG_SEP;
2128  for(int i=0; i<reg_count; i++)
2129  {
2130  mLogFileRight << "0x" << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(values[i]);
2131  if(i==(reg_count-1))
2132  mLogFileRight << std::endl;
2133  else
2134  mLogFileRight << LOG_SEP;
2135  }
2136 }
2137 
2139  int res = 0;
2140 
2141  res += ll_write_sensor_register( 0, 1, 0x3503, 0x04);
2142  res += ll_write_sensor_register( 1, 1, 0x3503, 0x04);
2143  res += ll_write_sensor_register( 0, 1, 0x3505, 0x00);
2144  res += ll_write_sensor_register( 1, 1, 0x3505, 0x00);
2145 
2146  return res==0;
2147 }
2148 #endif
2149 
2150 #ifdef SENSORS_MOD_AVAILABLE
2152 {
2153  if(!sensCap)
2154  return false;
2155 
2156  // Activate low level sync mechanism
2157  ll_activate_sync();
2158 
2159  mSyncEnabled = true;
2160  mSensPtr = sensCap;
2161 
2162  mSensPtr->setVideoPtr(this);
2163 
2164  return true;
2165 }
2166 #endif
2167 
2168 }
2169 
2170 }
2171 
2172 
2173 
The SensorCapture class provides sensor grabbing functions for the Stereolabs ZED Mini and ZED2 camer...
void updateTimestampOffset(uint64_t frame_ts)
Called by VideoCapture to update timestamp offset.
void setVideoPtr(video::VideoCapture *videoPtr)
Called by VideoCapture to set the pointer to it.
void setStartTimestamp(uint64_t start_ts)
Called by VideoCapture to sync timestamps reference point.
void setHue(int hue)
Set the Hue value.
int getBrightness()
Get the Brightness value.
bool setROIforAECAGC(CAM_SENS_POS side, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
Set Region Of Interest (ROI) for AECAGC control.
void resetBrightness()
Reset the Brightness value to default value.
const Frame & getLastFrame(uint64_t timeout_msec=100)
Get the last received camera image.
int getSharpness()
Get the Sharpness value.
int setLEDstatus(bool status)
Set the status of the camera led.
void resetGamma()
Reset the Gamma value to default value.
void resetHue()
Reset the Hue value to default value.
int getLEDstatus(bool *status)
Get the status of the camera led.
void setSaturation(int saturation)
Set the Saturation value.
int getGain(CAM_SENS_POS cam)
Get the current Gain value.
void saveAllSensorsRegisters(std::string filename)
Save all sensors ctrl register.
void resetAutoWhiteBalance()
Reset the automatic White Balance control value to default value.
void saveAllISPRegisters(std::string filename)
Save all ISP camera registers into a file.
int getSaturation()
Get the Saturation value.
int getHue()
Get the Hue value.
void resetSharpness()
Reset the Sharpness value to default value.
bool getAutoWhiteBalance()
Get the status of the automatic White Balance control.
int getGamma()
Get the Gamma value.
int getWhiteBalance()
Get the White Balance value.
void setSharpness(int sharpness)
Set the Sharpness value.
void setWhiteBalance(int wb)
Set the White Balance value (disable auto White Balance if active)
void setExposure(CAM_SENS_POS cam, int exposure)
Set the Exposure value (disable Exposure and Gain control if active)
VideoCapture(VideoParams params=VideoParams())
The default constructor.
bool initializeVideo(int devId=-1)
Open a ZED camera using the specified ID or searching for the first available.
void setContrast(int contrast)
Set the Contrast value.
int setAECAGC(bool active)
Enable/Disable the automatic Exposure and Gain control.
int getContrast()
Get the Contrast value.
bool enableAecAgcSensLogging(bool enable, int frame_skip=10)
Start logging to file of AEG/AGC camera registers.
void resetSaturation()
Reset the Saturation value to default value.
void resetAECAGC()
Reset the automatic Exposure and Gain control value to default value.
virtual ~VideoCapture()
The class destructor.
int getExposure(CAM_SENS_POS cam)
Get the current Exposure value.
bool enableSensorSync(sensors::SensorCapture *sensCap=nullptr)
Enable synchronizations between Camera frame and Sensors timestamps.
bool getROIforAECAGC(CAM_SENS_POS side, uint16_t &x, uint16_t &y, uint16_t &w, uint16_t &h)
Get the coordinates of the current ROI for AECAGC control.
void setGamma(int gamma)
Set the Gamma value.
void setBrightness(int brightness)
Set the Brightness value.
bool getAECAGC()
Get the status of the automatic Exposure and Gain control.
void setAutoWhiteBalance(bool active)
Enable/Disable the automatic White Balance control.
void setGain(CAM_SENS_POS cam, int gain)
Set the Gain value (disable Exposure and Gain control if active)
bool resetROIforAECAGC(CAM_SENS_POS side)
Reset the ROI for AECAGC control.
int getSerialNumber()
Retrieve the serial number of the connected camera.
void resetContrast()
Reset the Contrast value to default value.
void setColorBars(int side, bool c)
Utils fct to set Color Bars on Image.
int toggleLED(bool *value)
Toggle the status of the camera led.
uint64_t getWallTimestamp()
Get the current system clock as wall clock (it can have jumps if the system clock is updated by a syn...
Definition: defines.hpp:69
CAM_SENS_POS
Position of the Camera CMOS sensors.
@ RIGHT
The right sensor.
@ LEFT
The left sensor.
const unsigned char PRESET_GAMMA[9][16]
SL_DEVICE
Camera models.
@ ZED_M_CBS
ZED Mini new FW.
@ ZED_M
ZED Mini old FW.
@ ERROR
Definition: defines.hpp:87
The Frame struct containing the acquired video frames.
uint64_t timestamp
Timestamp in nanoseconds.
uint16_t height
Frame height.
uint64_t frame_id
Increasing index of frames.
uint8_t channels
Number of channels per pixel.
uint16_t width
Frame width.
uint8_t * data
Frame data in YUV 4:2:2 format.
size_t length
Size of the buffer.
void * start
Address of the first byte of the buffer.
The camera configuration parameters.
RESOLUTION res
Camera resolution.
FPS fps
Frames per second.
sl_oc::video::VideoParams params