summaryrefslogtreecommitdiff
path: root/src/camera
diff options
context:
space:
mode:
Diffstat (limited to 'src/camera')
-rw-r--r--src/camera/icamera.h39
-rw-r--r--src/camera/innomakerov9281.cpp523
-rw-r--r--src/camera/innomakerov9281.h63
-rw-r--r--src/camera/ov9281.cpp419
-rw-r--r--src/camera/ov9281.h90
-rw-r--r--src/camera/veye_i2c.cpp78
-rw-r--r--src/camera/veye_i2c.h25
-rw-r--r--src/camera/veyeimx287m.cpp252
-rw-r--r--src/camera/veyeimx287m.h32
-rw-r--r--src/camera/veyeimx287m_types.h14
10 files changed, 242 insertions, 1293 deletions
diff --git a/src/camera/icamera.h b/src/camera/icamera.h
index 39d358f..391ce55 100644
--- a/src/camera/icamera.h
+++ b/src/camera/icamera.h
@@ -20,14 +20,11 @@
#define slots slots_backup
#endif
-#include "image.h"
+// cpp
+#include <chrono>
-// class ICamera
-// {
-// public:
-// virtual bool setExposureTimeMs(int value) = 0;
-// virtual bool setGain(int value) = 0;
-// };
+// orpheus
+#include "image.h"
class ICamera
{
@@ -35,16 +32,32 @@ public:
virtual ~ICamera() = default;
public:
- virtual bool setExposureTimeUs(int value) = 0;
- virtual bool setGain(int value) = 0;
+ virtual bool set_autoExposure(const bool enable) = 0;
+ /*!
+ * \brief get_autoExposure - check if auto exposure is enabled
+ * \param ok - indicates successful read
+ * \return true if enabled, false otherwise
+ */
+
+ /*!
+ * \brief get_autoExposure - check if auto exposure is enabled
+ * \return non-empty value on success, empty value on failure
+ */
+ virtual std::optional<bool> get_autoExposure() = 0;
+
+ virtual bool set_exposureTime(const std::chrono::microseconds us) = 0;
+ virtual std::optional<const std::chrono::microseconds> get_exposureTime() = 0;
+
+ virtual bool set_autoGain(const bool enable) = 0;
+ virtual std::optional<bool> get_autoGain() = 0;
+
+ virtual bool set_gain(const float value) = 0;
+ virtual std::optional<float> get_gain() = 0;
+
virtual bool setLaserLevel(int value) = 0;
- virtual bool setSomething(int value) = 0;
public:
- libcamera::Signal<std::shared_ptr<Pixels>> newPixels;
- libcamera::Signal<std::shared_ptr<Image>> newImage;
std::function<void(std::shared_ptr<Pixels>)> newPixelsCallback;
- // std::function<void(std::shared_ptr<Image>)> newImageCallback;
std::function<void(Image &)> newImageCallback;
public:
diff --git a/src/camera/innomakerov9281.cpp b/src/camera/innomakerov9281.cpp
deleted file mode 100644
index 184601a..0000000
--- a/src/camera/innomakerov9281.cpp
+++ /dev/null
@@ -1,523 +0,0 @@
-#include "innomakerov9281.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/videodev2.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#include <iostream>
-#include <span>
-
-#include <QElapsedTimer>
-
-#include "constants.h"
-// #include "rotaryencoder.h"
-
-#define LOGD(...) \
- do \
- { \
- printf(__VA_ARGS__); \
- printf("\n"); \
- } while (0)
-
-#define DBG(fmt, args...) LOGD("%s:%d, " fmt, __FUNCTION__, __LINE__, ##args);
-
-extern uint64_t dq_elapsed_ns;
-extern uint64_t get_elapsed_ns;
-extern uint64_t sum_elapsed_ns;
-extern uint64_t corr_elapsed_ns;
-extern uint64_t max_elapsed_ns;
-extern uint64_t value_elapsed_ns;
-extern uint64_t rot_elapsed_ns;
-extern uint64_t pix_elapsed_ns;
-extern uint64_t dropped_count;
-
-// constexpr char videoDevice[] = "/dev/video0";
-
-InnoMakerOV9281::InnoMakerOV9281() {}
-
-InnoMakerOV9281::~InnoMakerOV9281()
-{
- m_streamThread.request_stop();
- m_streamThread.join();
-
- m_someThread.request_stop();
- m_someThread.join();
-
- int ret{-1};
-
- for (int i = 0; i < BUFFER_COUNT; ++i)
- {
- ret = munmap(video_buffer_ptr[i], img_size);
-
- if (ret < 0)
- {
- DBG("Munmap failed!!.");
- }
- }
-
- // std::cout << __func__ << std::endl;
- if (m_cam_fd >= 0)
- {
- int ret = close(m_cam_fd);
-
- if (ret == -1)
- {
- // std::cout << __func__
- // << ": cannot close camera: " << strerror(errno)
- // << std::endl;
- }
- };
-
- // std::cout << __func__ << ": success" << std::endl;
-}
-
-std::vector<std::shared_ptr<ICamera> > InnoMakerOV9281::search()
-{
- // return only one camera for now
- std::cout << std::boolalpha;
- auto cam = std::make_shared<InnoMakerOV9281>();
-
- if (!cam->init())
- return {};
-
- if (!cam->setExposureTimeUs(30))
- return {};
-
- if (!cam->setLaserLevel(1))
- return {};
-
- if (!cam->setGain(2))
- return {};
-
- if (!cam->setSomething(0)) {
- return {};
- }
-
- // m_someThread = std::jthread{[=](std::stop_token stopToken) {
- // std::cout << "InnoMakerOV9281: start stream" << std::endl;
- // sleep(5);
-
- // static int i = 0;
- // while (!stopToken.stop_requested()) {
- // cam->setSomething(i);
- // i -= 1;
- // }
- // }};
-
- return {cam};
-}
-
-bool InnoMakerOV9281::startStream()
-{
- int buffer_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- auto ret = ioctl(m_cam_fd, VIDIOC_STREAMON, &buffer_type);
-
- if (ret != 0) {
- DBG("ioctl(VIDIOC_STREAMON) failed %d(%s)", errno, strerror(errno));
- return false;
- }
-
- m_streamThread = std::jthread{[&](std::stop_token stopToken) {
- std::cout << "InnoMakerOV9281: start stream" << std::endl;
-
- // Image image;
- // std::shared_ptr<Image> imageCopy = std::make_shared<Image>();
- while (!stopToken.stop_requested())
- {
- size_t imageIndex{};
-
- // if (!getImage(image))
- if (!getImage(imageIndex))
- break;
-
- continue;
-
- // auto image = m_images[imageIndex];
-
- // // // FIXME: backup emit value
- // // #ifdef emit
- // // #undef emit
- // // // std::cout << "emit new image" << std::endl << std::flush;
- // // // newImage.emit(image);
- // if (newImageCallback) {
- // // memcpy(imageCopy.get(), &image, sizeof(Image));
- // // newImageCallback(imageCopy);
- // newImageCallback(image);
- // }
- // // continue;
- // // // // newPixels.emit(pixels);
- // // auto &img = *image;
- // // image->rotate();
- // // img.rotate();
- // image.rotate();
- // // image.rotate();
- // if (newPixelsCallback) {
- // // auto pixels = image->pixels();
- // auto pixels = image.pixels();
- // newPixelsCallback(pixels);
- // }
- // continue;
- }
- // #define emit
- // #endif
- std::cout << "InnoMakerOV9281: stream interruption requested"
- << std::endl;
- }};
-
- return true;
-}
-
-bool InnoMakerOV9281::init()
-{
- if (!openCam())
- return false;
-
- if (!selectCam())
- return false;
-
- if (!initCam())
- return false;
-
- return true;
-}
-
-bool InnoMakerOV9281::setExposureTimeUs(int valueUs)
-{
- return true;
- std::cout << __func__ << ": " << valueUs << std::endl << std::flush;
-
- /*
- * Shutter Time. Value is from 8721ns to 8721*885ns, must be integral
- * multiple of 8721ns .
- * 8721xN(N =1,2,3,4,5.....855)
- */
- // constexpr int exposureStep{8721};
- // constexpr int maxExposureStepMultiplier{885};
- // auto valueNs = valueUs;
- // valueNs = (valueNs / exposureStep) * exposureStep;
-
- // std::clamp(valueNs, exposureStep, exposureStep * maxExposureStepMultiplier);
- // setGain(rand() % 254);
- // setGain(3);
- // setLaserLevel(rand() % 0x7fffffff);
- // setLaserLevel(rand() % 100);
- // int exp = rand() % 10;
- // return setCamParam(V4L2_CID_EXPOSURE, exp * exp * exp * exp * exp * exp);
- return setCamParam(V4L2_CID_EXPOSURE, valueUs);
-}
-
-bool InnoMakerOV9281::setGain(int value)
-{
- std::cout << __func__ << ": " << value << std::endl << std::flush;
-
- // return setCamParam(V4L2_CID_GAIN, value);
- // FIXME: tmp workaround for imx287llr
- return true;
-}
-
-bool InnoMakerOV9281::setLaserLevel(int value)
-{
- std::cout << __func__ << ": " << value << std::endl << std::flush;
-
- // return setCamParam(V4L2_CID_FLASH_TIMEOUT, value);
-
- // FIXME: tmp workaround for imx287llr
- return true;
-}
-
-bool InnoMakerOV9281::setSomething(int value)
-{
- std::cout << __func__ << ": " << value << std::endl << std::flush;
-
- // return setCamParam(V4L2_CID_FLASH_INTENSITY, value);
- // FIXME: tmp workaround for imx287llr
- return true;
-}
-
-bool InnoMakerOV9281::setCamParam(unsigned int v4l2controlId, int value)
-{
- v4l2_control ctl{v4l2controlId, value};
-
- int ret = ioctl(m_cam_fd, VIDIOC_S_CTRL, &ctl);
-
- if (ret < 0)
- {
- fprintf(stderr,
- "cannot set cam param: id - %d, error - '%s'\n",
- v4l2controlId,
- strerror(errno));
- fflush(stderr);
-
- return false;
- }
-
- ret = ioctl(m_cam_fd, VIDIOC_G_CTRL, &ctl);
-
- if (ret < 0)
- {
- fprintf(stderr,
- "cannot get cam param: id - %d, error - '%s'\n",
- v4l2controlId,
- strerror(errno));
-
- fflush(stderr);
-
- return false;
- }
-
- std::cout << __func__ << ": new value is " << ctl.value << std::endl;
-
- return true;
-}
-
-bool InnoMakerOV9281::openCam()
-{
- m_cam_fd = open(videoDevice, O_RDWR);
-
- if (m_cam_fd < 0)
- {
- fprintf(stderr,
- "cannot open cam '%s', error: '%s'\n",
- videoDevice,
- strerror(errno));
- return false;
- }
-
- return true;
-}
-
-bool InnoMakerOV9281::selectCam(int camIdx)
-{
- int input = camIdx;
- int ret = ioctl(m_cam_fd, VIDIOC_S_INPUT, &input);
-
- if (ret < 0)
- {
- fprintf(stderr,
- "cannot select cam: idx - %d, error - '%s'\n",
- camIdx,
- strerror(errno));
-
- return false;
- }
-
- return true;
-}
-
-bool InnoMakerOV9281::initCam()
-{
- v4l2_format format;
- memset(&format, 0, sizeof(v4l2_format));
- format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- format.fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;
- format.fmt.pix.width = img_width;
- format.fmt.pix.height = img_height;
-
- int ret = ioctl(m_cam_fd, VIDIOC_TRY_FMT, &format);
-
- if (ret < 0)
- {
- fprintf(stderr,
- "cannot try cam format: error - '%s'\n",
- strerror(errno));
-
- return false;
- }
-
- // TODO: remove this?
- format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
- ret = ioctl(m_cam_fd, VIDIOC_S_FMT, &format);
-
- if (ret < 0)
- {
- fprintf(stderr,
- "cannot set cam format: error - '%s'\n",
- strerror(errno));
-
- return false;
- }
-
- struct v4l2_requestbuffers request;
- request.count = BUFFER_COUNT;
- request.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- request.memory = V4L2_MEMORY_MMAP;
- ret = ioctl(m_cam_fd, VIDIOC_REQBUFS, &request);
-
- if (ret < 0) {
- fprintf(stderr, "cannot set cam request buffers: ioctl error - '%s'\n", strerror(errno));
-
- return false;
- }
-
- if (request.count < BUFFER_COUNT)
- {
- fprintf(stderr, "cannot set cam request buffers\n");
-
- return false;
- }
-
- struct v4l2_buffer buffer;
- memset(&buffer, 0, sizeof(buffer));
- buffer.type = request.type;
- buffer.memory = V4L2_MEMORY_MMAP;
-
- for (uint32_t i = 0; i < request.count; i++)
- {
- buffer.index = i;
- ret = ioctl(m_cam_fd, VIDIOC_QUERYBUF, &buffer);
-
- if (ret < 0)
- {
- DBG("ioctl(VIDIOC_QUERYBUF) failed %d(%s)", errno, strerror(errno));
- return false;
- }
-
- DBG("buffer.length: %d", buffer.length);
- DBG("buffer.m.offset: %d", buffer.m.offset);
- video_buffer_ptr[i] = (uint8_t *)
- mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, m_cam_fd, buffer.m.offset);
- if (video_buffer_ptr[i] == MAP_FAILED) {
- DBG("mmap() failed %d(%s)", errno, strerror(errno));
- return false;
- }
-
- buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buffer.memory = V4L2_MEMORY_MMAP;
- buffer.index = i;
- ret = ioctl(m_cam_fd, VIDIOC_QBUF, &buffer);
- if (ret != 0)
- {
- DBG("ioctl(VIDIOC_QBUF) failed %d(%s)", errno, strerror(errno));
- return false;
- }
- }
-
- // int buffer_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- // ret = ioctl(m_cam_fd, VIDIOC_STREAMON, &buffer_type);
- // if (ret != 0)
- // {
- // DBG("ioctl(VIDIOC_STREAMON) failed %d(%s)", errno, strerror(errno));
- // return false;
- // }
-
- DBG("cam init done.");
-
- return true;
-}
-
-// Image &InnoMakerOV9281::getImage()
-// bool InnoMakerOV9281::getImage(Image &image)
-bool InnoMakerOV9281::getImage(size_t &imageIndex)
-// TODO: get Image from video_buffer_ptr
-{
- static struct timeval curr, prev;
- static uint16_t counter = 0;
- gettimeofday(&curr, NULL);
- ++counter;
-
- double elapsedTime = (curr.tv_sec - prev.tv_sec) * 1000.0; // sec to ms
- elapsedTime += (curr.tv_usec - prev.tv_usec) / 1000.0; // us to ms
-
- if (elapsedTime > 1000.)
- {
- fprintf(stderr,
- "fps: %d\tdropped: %d\tsec: %d\t"
- "dq: %d\tget: %d\trot: %d\tpix: %d\tsum: %d,\tcorr: "
- "%d,\tval: %d\n",
- counter,
- dropped_count,
- curr.tv_sec % 1000,
- dq_elapsed_ns / 1000 / counter,
- get_elapsed_ns / 1000 / counter,
- rot_elapsed_ns / 1000 / counter,
- pix_elapsed_ns / 1000 / counter,
- sum_elapsed_ns / 1000 / counter,
- corr_elapsed_ns / 1000 / counter,
- // max_elapsed_ns / 1000 / counter,
- value_elapsed_ns / 1000 / counter);
-
- dq_elapsed_ns = 0;
- get_elapsed_ns = 0;
- sum_elapsed_ns = 0;
- corr_elapsed_ns = 0;
- max_elapsed_ns = 0;
- value_elapsed_ns = 0;
- rot_elapsed_ns = 0;
- pix_elapsed_ns = 0;
- dropped_count = 0;
-
- counter = 0;
- prev = curr;
- }
-
- int ret;
- struct v4l2_buffer buffer;
-
- memset(&buffer, 0, sizeof(buffer));
- buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buffer.memory = V4L2_MEMORY_MMAP;
- buffer.index = BUFFER_COUNT;
-
- {
- QElapsedTimer t;
- t.start();
- ret = ioctl(m_cam_fd, VIDIOC_DQBUF, &buffer);
- dq_elapsed_ns += t.nsecsElapsed();
- }
-
- if (ret != 0) {
- DBG("ioctl(VIDIOC_DQBUF) failed %d(%s)", errno, strerror(errno));
- return false;
- }
-
- if (buffer.index < 0 || buffer.index >= BUFFER_COUNT)
- {
- DBG("invalid buffer index: %d", buffer.index);
- return false;
- }
-
- // auto &image = video_buffer_ptr[buffer.index];
- imageIndex = buffer.index;
- auto &image = m_images[buffer.index];
- image.height = img_height;
- image.width = img_width;
- // TODO: fill
- // image.counters.encoderPosition = RotaryEncoder::instance()->position();
- image.counters.measurementCounter = buffer.sequence;
-
- static int64_t prevCounter = buffer.sequence;
- dropped_count += buffer.sequence - prevCounter - 1;
- prevCounter = buffer.sequence;
-
- image.counters.timestampUs = buffer.timestamp.tv_sec * 1000 * 1000 + buffer.timestamp.tv_usec;
-
- {
- QElapsedTimer t;
- t.start();
- // memcpy(&image.data, video_buffer_ptr[buffer.index], img_size);
- // std::cout << (void *) video_buffer_ptr[buffer.index] << std::endl;
- get_elapsed_ns += t.nsecsElapsed();
- }
-
- static bool done{false};
-
- if (!done) {
- // memcpy(image.data.data(), video_buffer_ptr[buffer.index], img_size);
- done = true;
- }
-
- ret = ioctl(m_cam_fd, VIDIOC_QBUF, &buffer);
-
- if (ret != 0) {
- DBG("ioctl(VIDIOC_QBUF) failed %d(%s)", errno, strerror(errno));
- return false;
- }
-
- return true;
-}
diff --git a/src/camera/innomakerov9281.h b/src/camera/innomakerov9281.h
deleted file mode 100644
index 7f2d206..0000000
--- a/src/camera/innomakerov9281.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#pragma once
-
-#include <cstdint>
-
-#include <thread>
-
-#include "constants.h"
-#include "image.h"
-
-#include "icamera.h"
-
-class InnoMakerOV9281 : public ICamera
-{
- constexpr static char videoDevice[] = "/dev/video0";
-
-public:
- using buffer_t = std::array<uint8_t, img_size>;
-
-public:
- InnoMakerOV9281();
- ~InnoMakerOV9281();
-
-public:
- static std::vector<std::shared_ptr<ICamera>> search();
-
-public:
- bool startStream() override;
-
- bool init();
-
- bool setExposureTimeUs(int value) override;
- bool setGain(int value) override;
-
- bool setLaserLevel(int value) override;
-
- bool setSomething(int value) override;
-
- // bool getImage(Image &image);
- bool getImage(size_t &image);
- // Image &getImage();
-
-public:
- libcamera::Signal<std::shared_ptr<Pixels>> newPixels;
- libcamera::Signal<std::shared_ptr<Image>> newImage;
-
-private:
- bool setCamParam(unsigned int v4l2controlId, int value);
- bool openCam();
- bool selectCam(int camIdx = 0);
- bool initCam();
-
-private:
- int m_cam_fd{-1};
- static constexpr uint8_t BUFFER_COUNT{3};
- // #ifdef USER_PTR
- Image m_images[BUFFER_COUNT];
- // #else
- uint8_t *video_buffer_ptr[BUFFER_COUNT];
- // #endif
- // buffer_t m_buf;
- std::jthread m_streamThread;
- static inline std::jthread m_someThread;
-};
diff --git a/src/camera/ov9281.cpp b/src/camera/ov9281.cpp
deleted file mode 100644
index 8f84255..0000000
--- a/src/camera/ov9281.cpp
+++ /dev/null
@@ -1,419 +0,0 @@
-#include "ov9281.h"
-
-#include <iostream>
-#include <thread>
-
-#include <string.h>
-#include <sys/mman.h>
-
-#include <libcamera/camera.h>
-#include <libcamera/camera_manager.h>
-#include <libcamera/control_ids.h>
-#include <libcamera/framebuffer_allocator.h>
-#include <libcamera/request.h>
-
-#include "image.h"
-#include "macro.h"
-#include "pixels.h"
-#include "rotaryencoder.h"
-#include "typedefs.h"
-
-#include <QElapsedTimer>
-
-QElapsedTimer timer;
-size_t fpsCounter{0};
-
-OV9281::OV9281(const std::shared_ptr<libcamera::Camera> &camera)
- : INIT_FIELD(camera)
-{
- timer.start();
- std::cout << __func__ << ":\tid: " << m_camera->id();
-}
-
-OV9281::~OV9281()
-{
- for (auto &[fd, mem] : m_mappedBuffers)
- {
- munmap(mem.first, mem.second);
- }
-
- m_camera->release();
-}
-
-bool OV9281::init()
-{
- if (m_camera->acquire() != EXIT_SUCCESS)
- {
- std::cerr << __func__ << ": " << m_camera->id()
- << ": cannot acquire camera." << std::endl;
-
- return false;
- }
-
- m_config = m_camera->generateConfiguration({libcamera::StreamRole::Raw});
-
- if (m_config->empty())
- {
- std::cerr << __func__ << ": " << m_camera->id()
- << ": cannot generate configuration" << std::endl;
-
- return false;
- }
-
- // m_config->orientation = libcamera::Orientation::Rotate90;
-
- libcamera::StreamConfiguration &streamConfig = m_config->at(0);
-
- std::cout << "supported pixel formats:\n";
-
- for (const auto &pixelFormat : streamConfig.formats().pixelformats())
- {
- std::cout << "\t" << pixelFormat.toString() << std::endl;
-
- for (const auto &size : streamConfig.formats().sizes(pixelFormat))
- {
- std::cout << "\t\t" << size.toString() << std::endl;
- }
- }
-
- streamConfig.pixelFormat = OV9281::pixelFormat;
- streamConfig.bufferCount = OV9281::bufferCount;
-
- if (!validateConfig())
- {
- return false;
- }
-
- if (!applyConfig()) {
- return false;
- }
-
- return true;
-}
-
-bool OV9281::validateConfig()
-{
- using namespace libcamera;
-
- auto status = m_config->validate();
-
- // WARNING: unsafe
-
- switch (status)
- {
- case CameraConfiguration::Status::Valid: {
- std::cout << __func__ << ": " << "config is valid" << std::endl;
- break;
- }
- case CameraConfiguration::Status::Adjusted: {
- if (m_config->empty())
- {
- std::cerr << __func__ << ": " << "config is adjusted, but empty"
- << std::endl;
- return false;
- }
-
- libcamera::StreamConfiguration &streamConfig = m_config->at(0);
- std::cout << __func__
- << ":\tpixelFormat: " << streamConfig.pixelFormat.toString()
- << std::endl;
- std::cout << __func__ << ":\tbufferCount: " << streamConfig.bufferCount
- << std::endl;
- // std::cout << __func__ << ":\torientation: " << m_config->orientation
- // << std::endl;
- break;
- }
- case CameraConfiguration::Status::Invalid: {
- std::cerr << __func__ << ":\tconfig is invalid" << std::endl;
-
- return false;
- }
- }
-
- return true;
-}
-
-bool OV9281::applyConfig()
-{
- // FIXME: may crassh even on success (e.g. by setting pixelFormat to "8")
- if (m_camera->configure(m_config.get()) != EXIT_SUCCESS)
- {
- std::cerr << __func__ << ":\tcannot apply config" << std::endl;
-
- return false;
- }
-
- return true;
-}
-
-/*
- * Signals operate in the libcamera CameraManager thread context, so it is
- * important not to block the thread for a long time, as this blocks internal
- * processing of the camera pipelines, and can affect realtime performance.
- */
-void OV9281::onRequestCompleted(libcamera::Request *completed_request)
-{
- fpsCounter++;
-
- if (timer.elapsed() > 1000) {
- std::cout << "fps: " << fpsCounter << std::endl;
- timer.restart();
- fpsCounter = 0;
- }
-
- using namespace libcamera;
-
- if (completed_request->status() == Request::RequestCancelled)
- {
- std::cerr << __func__ << ":\trequest canceled" << std::endl;
-
- return;
- }
-
- const auto &buffers = completed_request->buffers();
-
-#if 1
- for (auto [stream, buffer] : buffers)
- {
- const auto &streamConfig = stream->configuration();
- const auto &imageSize = streamConfig.size;
- const auto &pixelFormat = streamConfig.pixelFormat;
- const auto &stride = streamConfig.stride;
-
- const FrameMetadata &metadata = buffer->metadata();
-
- for (size_t i = 0; i < buffer->planes().size(); ++i)
- {
- const FrameBuffer::Plane &plane = buffer->planes()[i];
- const FrameMetadata::Plane &metaplane = buffer->metadata()
- .planes()[i];
-
- size_t size = std::min(metaplane.bytesused, plane.length);
- // std::cout << "size is: " << size << std::endl;
- void *data = m_mappedBuffers[plane.fd.get()].first;
-
- auto img = std::make_shared<Image>();
-
- img->width = imageSize.width;
- img->height = imageSize.height;
-
- // img->dataSize = size;
- // img->stride = stride;
- img->pixelFormat = pixelFormat;
- img->counters.measurementCounter = metadata.sequence;
- img->counters.timestampUs = metadata.timestamp / 1000;
- img->counters.encoderPosition = RotaryEncoder::instance()->position();
-
- img->copyFromData(data, size);
- // memcpy(img->data, data, size);
- img->rotate();
-
- auto pixels = img->pixels();
-// FIXME: backup emit value
-#ifdef emit
-#undef emit
- if (!pixels) {
- std::cerr << "emit empty pixels" << std::endl;
- }
- newImage.emit(img);
- // newPixels.emit(pixels);
-#define emit
-#endif
- }
- }
-#endif
- const libcamera::ControlList &metadata = completed_request->metadata();
- const ControlInfoMap &control_map = m_camera->controls();
- // const ControlIdMap & ctrlIdMap = control_map.idmap();
-
- auto frameDurationCtrl = control_map.find(&controls::FrameDurationLimits);
- double fps = frameDurationCtrl == control_map.end() ?
- std::numeric_limits<double>::quiet_NaN() :
- (1e6 / frameDurationCtrl->second.min().get<int64_t>());
-
- auto exp = metadata.get(controls::ExposureTime);
- auto ag = metadata.get(controls::AnalogueGain);
- auto ae = metadata.get(controls::AeEnable);
- // auto br= metadata.get(controls::Brightness);
- static auto lastControls = completed_request->controls();
-
- completed_request->reuse(Request::ReuseBuffers);
- // completed_request->controls().set(libcamera::controls::AeEnable, false);
- // completed_request->controls()
- // .set(libcamera::controls::draft ::NoiseReductionMode,
- // libcamera::controls::draft ::NoiseReductionModeEnum ::
- // NoiseReductionModeHighQuality);
-
- completed_request->controls().set(libcamera::controls::ExposureTime,
- m_exposureTime);
-
- m_camera->queueRequest(completed_request);
-}
-
-std::vector<std::shared_ptr<OV9281>> OV9281::search(
- std::unique_ptr<libcamera::CameraManager> &manager)
-{
- std::vector<std::shared_ptr<OV9281>> result;
-
- for (const auto &camera : manager->cameras())
- {
- auto id = camera->id();
- auto c = manager->get(id);
- // auto ov9281 = std::shared_ptr<OV9281>(new OV9281(c));
-
- // if (!ov9281->init())
- // {
- // continue;
- // }
-
- // result.push_back(ov9281);
- }
-
- return result;
-}
-
-bool OV9281::startStream()
-{
- if (m_config->empty())
- {
- std::cerr << __func__ << ":\tconfig is empty" << std::endl;
- return false;
- }
-
- auto &streamConfig = m_config->at(0);
- m_allocator = std::make_unique<libcamera::FrameBufferAllocator>(m_camera);
- auto stream = streamConfig.stream();
- auto ret = m_allocator->allocate(stream);
-
- // TODO: check if zero
- if (ret < 0)
- {
- std::cerr << __func__ << ":\tcan't allocate buffers: " << strerror(ret)
- << std::endl;
- return false;
- }
-
- auto allocatedCount = ret;
- std::cout << __func__ << ":\tallocated " << allocatedCount
- << " buffers for stream" << std::endl;
-
- const auto &buffers = m_allocator->buffers(stream);
-
- for (const auto &buffer : buffers)
- {
- auto request = m_camera->createRequest();
-
- if (!request)
- {
- std::cerr << __func__ << ":\tcan't create request" << std::endl;
-
- return false;
- }
-
- // TODO: try multiple buffers per request and compare performance
- ret = request->addBuffer(stream, buffer.get());
-
- if (ret < 0)
- {
- std::cerr << __func__
- << ":\tcan't set buffer for request: " << strerror(ret)
- << std::endl;
-
- return false;
- }
-
- for (const auto &plane : buffer->planes())
- {
- void *memory = mmap(NULL,
- plane.length,
- PROT_READ,
- MAP_SHARED,
- plane.fd.get(),
- 0);
- m_mappedBuffers[plane.fd.get()] = std::make_pair(memory,
- plane.length);
- }
-
- std::int64_t lowerUS = 1 * 1000 * 1000 / desiredFPS;
- std::int64_t higherUS = lowerUS;
- std::int64_t value_pair[2] = {higherUS / 2, higherUS};
- request->controls().set(libcamera::controls::AnalogueGain, 1.0);
- request->controls().set(libcamera::controls::ExposureTime, 100);
- request->controls().set(libcamera::controls::FrameDurationLimits,
- libcamera::Span<const std::int64_t, 2>(
- value_pair));
-
- m_requests.push_back(std::move(request));
- }
-
- m_camera->requestCompleted.connect(this, &OV9281::onRequestCompleted);
-
- // FIXME: memleak
- std::unique_ptr<libcamera::ControlList> camcontrols{
- new libcamera::ControlList()};
-
- {
- using namespace std::chrono_literals;
- std::this_thread::sleep_for(500ms);
- }
-
- ret = m_camera->start(camcontrols.get());
-
- if (ret)
- {
- std::cerr << __func__ << ":\tfailed to start camera: " << strerror(ret)
- << std::endl;
-
- return false;
- }
-
- for (auto &request : m_requests)
- {
- ret = m_camera->queueRequest(request.get());
-
- if (ret)
- {
- std::cerr << __func__
- << ":\tfailed to queue request: " << strerror(ret)
- << std::endl;
-
- return false;
- }
- }
-
- return true;
-}
-
-void OV9281::printControls()
-{
- using namespace libcamera;
- const libcamera::ControlInfoMap &control_map = m_camera->controls();
-
- // for (const auto & [id, info]: control_map)
- for (const std::pair<const ControlId *, ControlInfo> &pair : control_map)
- {
- const ControlId *const &id = pair.first;
- const ControlInfo &info = pair.second;
-
- std::cout << "\tc " << id->name() << " (" << id->id()
- << "): " << info.toString()
- << (info.def().isNone() ?
- "" :
- " (dflt:" + info.def().toString() + ")");
-
- if (!info.values().size())
- {
- std::cout << std::endl;
- continue;
- }
-
- std::cout << " - [";
-
- for (const auto &v : info.values())
- {
- std::cout << " " << v.toString();
- }
-
- std::cout << " ]\n";
- }
-}
diff --git a/src/camera/ov9281.h b/src/camera/ov9281.h
deleted file mode 100644
index e4b7417..0000000
--- a/src/camera/ov9281.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#pragma once
-
-#include <map>
-#include <memory>
-#include <vector>
-
-#include <libcamera/formats.h>
-
-#include <QObject>
-
-#include "icamera.h"
-
-namespace libcamera {
-class Camera;
-class CameraConfiguration;
-class CameraManager;
-class FrameBufferAllocator;
-class Request;
-} // namespace libcamera
-
-class Image;
-class Pixels;
-
-class OV9281 : public QObject, public ICamera
-{
- // Q_OBJECT
-
-public:
- ~OV9281();
-
-public:
- static std::vector<std::shared_ptr<OV9281>> search(
- std::unique_ptr<libcamera::CameraManager> &manager);
-
- // public functions
-public:
- bool startStream() override;
- void printControls();
-
- bool setExposureTimeUs(int value) override
- {
- assert(false);
- return false;
- };
- bool setGain(int value) override
- {
- assert(false);
- return false;
- };
- bool setLaserLevel(int value) override
- {
- assert(false);
- return false;
- };
-
- // signals
-public:
- // TODO: image->pixels in separate thread
- // TODO: respect sender/receiver threads
- // libcamera::Signal<std::shared_ptr<Pixels>> newPixels;
- // libcamera::Signal<std::shared_ptr<Image>> newImage;
-
-private:
- explicit OV9281(const std::shared_ptr<libcamera::Camera> &camera);
-
- // private functions
-private:
- bool init();
- bool validateConfig();
- bool applyConfig();
-
- void onRequestCompleted(libcamera::Request *completed_request);
-
- // constants
-private:
- static inline constexpr auto pixelFormat{libcamera::formats::R8};
- static inline constexpr unsigned int bufferCount{2};
- static inline constexpr size_t desiredFPS{144};
-
- // member variables
-private:
- std::shared_ptr<libcamera::Camera> m_camera{nullptr};
- std::unique_ptr<libcamera::CameraConfiguration> m_config{nullptr};
- std::map<int, std::pair<void *, unsigned int>> m_mappedBuffers;
- std::vector<std::unique_ptr<libcamera::Request>> m_requests;
- std::unique_ptr<libcamera::FrameBufferAllocator> m_allocator{nullptr};
-
- // TODO: set exposureTime from outside
- int32_t m_exposureTime{3000};
-};
diff --git a/src/camera/veye_i2c.cpp b/src/camera/veye_i2c.cpp
index c34da51..b9ad2fa 100644
--- a/src/camera/veye_i2c.cpp
+++ b/src/camera/veye_i2c.cpp
@@ -12,7 +12,9 @@
#include "veyeimx287m_types.h"
-bool veye::imx287m::i2cRead(int fd, uint8_t i2c_addr, uint16_t reg, uint32_t &value)
+std::optional<uint32_t> veye::imx287m::i2c_read(int fd,
+ uint8_t i2c_addr,
+ uint16_t reg)
{
int err;
uint8_t bufin[2] = {reg >> 8, reg & 0xff};
@@ -42,56 +44,16 @@ bool veye::imx287m::i2cRead(int fd, uint8_t i2c_addr, uint16_t reg, uint32_t &va
//printf("Read i2c addr %02X\n", i2c_addr);
if (err != msgset.nmsgs) {
std::cerr << "read i2c err " << err << std::endl;
- return false;
+ return {};
}
- value = ntohl(*(uint32_t *) bufout);
- // fprintf(stderr, "addr %04x : value %08x \n", reg + i, value);
+ const auto result = ntohl(*(uint32_t *) bufout);
+ // fprintf(stderr, "addr %04x : value %08x \n", reg + i, result);
- return true;
+ return result;
}
-bool veye::imx287m::test(uint32_t value)
-{
- // const std::string i2cDevName{"/dev/i2c-10"};
- const std::string i2cDevName{"/dev/i2c-2"};
- constexpr uint32_t i2cDevAddr{0x3b};
- int fd = open(i2cDevName.c_str(), O_RDWR);
-
- if (!fd) {
- std::cerr << "cannot open i2c device " << i2cDevName << ", error: " << strerror(errno)
- << std::endl;
- return false;
- }
-
- if (ioctl(fd, I2C_SLAVE_FORCE, i2cDevAddr) < 0) {
- std::cerr << "cannot set i2c slave. dev: " << i2cDevName << ", addr: " << i2cDevAddr
- << ", error: " << strerror(errno) << std::endl;
-
- return false;
- }
-
- uint32_t expTime{0};
- // if (!i2cRead(fd, i2cDevAddr, (uint16_t) veye::imx287m::Register::ME_Time, expTime)) {
- // return false;
- // }
-
- // std::cout << "exp time is: " << expTime << std::endl;
- std::cout << "set exp time to " << value;
-
- if (!i2cWrite(fd, (uint16_t) veye::imx287m::Register::ME_Time, value)) {
- return false;
- }
-
- if (!i2cRead(fd, i2cDevAddr, (uint16_t) veye::imx287m::Register::ME_Time, expTime)) {
- return false;
- }
- std::cout << "\texp time is: " << expTime << std::endl;
-
- return true;
-}
-
-bool veye::imx287m::i2cWrite(int fd, uint16_t reg, const uint32_t value)
+bool veye::imx287m::i2c_write(int fd, uint16_t reg, const uint32_t value)
{
uint8_t msg[] = {reg >> 8, reg & 0xff, value >> 24, value >> 16, value >> 8, value >> 0};
int len = sizeof(msg) / sizeof(msg[0]);
@@ -120,8 +82,32 @@ veye::imx287m::i2c::~i2c()
}
}
+std::optional<uint32_t> veye::imx287m::i2c::read(uint16_t reg)
+{
+ if (m_fd == -1 && !open()) {
+ return {};
+ }
+
+ return i2c_read(m_fd, m_address, reg);
+}
+
+bool veye::imx287m::i2c::write(uint16_t reg, const uint32_t value)
+{
+ if (m_fd == -1 && !open()) {
+ return false;
+ }
+
+ return i2c_write(m_fd, reg, value);
+}
+
bool veye::imx287m::i2c::open()
{
+ if (m_fd != -1) {
+ std::cout << __func__ << ": " << m_name
+ << " is already open, do nothing" << std::endl;
+ return true;
+ }
+
m_fd = ::open(m_name.c_str(), O_RDWR);
if (!m_fd) {
diff --git a/src/camera/veye_i2c.h b/src/camera/veye_i2c.h
index 001d483..24ef10b 100644
--- a/src/camera/veye_i2c.h
+++ b/src/camera/veye_i2c.h
@@ -1,6 +1,7 @@
#pragma once
#include <cstdint>
+#include <optional>
#include <string>
namespace veye {
@@ -12,20 +13,30 @@ public:
~i2c();
public:
- bool read(uint16_t reg, uint32_t &value);
- bool write(uint16_t reg, const uint32_t value);
-
-private:
+ /*!
+ * \brief open - open i2c device with `name` passed to constructor
+ * \return - true on success or if already open, false otherwise
+ */
bool open();
+ std::optional<uint32_t> read(uint16_t reg);
+ bool write(uint16_t reg, const uint32_t value);
+
private:
int m_fd{-1};
std::string m_name;
int m_address{-1};
};
-bool i2cRead(int fd, uint8_t i2c_addr, uint16_t reg, uint32_t &value);
-bool i2cWrite(int fd, uint16_t reg, const uint32_t value);
-bool test(uint32_t value);
+/*!
+ * \brief i2c_read - read device registers using i2c
+ * \param fd - device file descriptor
+ * \param i2c_addr - i2c adderr
+ * \param reg - register
+ * \param value - value to set
+ * \return non-empty register value on success, empty value on failure
+ */
+std::optional<uint32_t> i2c_read(int fd, uint8_t i2c_addr, uint16_t reg);
+bool i2c_write(int fd, uint16_t reg, const uint32_t value);
} // namespace imx287m
} // namespace veye
diff --git a/src/camera/veyeimx287m.cpp b/src/camera/veyeimx287m.cpp
index b8fdbb4..a03aa83 100644
--- a/src/camera/veyeimx287m.cpp
+++ b/src/camera/veyeimx287m.cpp
@@ -9,20 +9,15 @@
#include <sys/mman.h>
#include <unistd.h>
-#include <execution>
#include <iostream>
-#include <ranges>
-#include <span>
#include <QElapsedTimer>
+// orpheus
#include "camera/veye_i2c.h"
#include "constants.h"
-#include "httpservice.h"
-#include "imagealgos.h"
-#include "mem_utils.h"
-#include "pixels.h"
-// #include "rotaryencoder.h"
+#include "protocols/httpserver.h"
+#include "veyeimx287m_types.h"
static const struct v4l2_format_info
{
@@ -232,7 +227,9 @@ VeyeIMX287m::~VeyeIMX287m()
if (m_cam_fd >= 0) {
if (close(m_cam_fd) == -1) {
- std::cout << __func__ << ": cannot close camera: " << strerror(errno) << std::endl;
+ std::cout << __func__
+ << ": cannot close camera: " << strerror(errno)
+ << std::endl;
}
};
@@ -242,35 +239,26 @@ VeyeIMX287m::~VeyeIMX287m()
std::vector<std::shared_ptr<ICamera> > VeyeIMX287m::search()
{
// return only one camera for now
- std::cout << std::boolalpha;
- auto cam = std::make_shared<VeyeIMX287m>();
+ const auto cam = std::make_shared<VeyeIMX287m>();
if (!cam->init())
return {};
- if (!cam->setExposureTimeUs(30))
+ // if (!cam->set_autoExposure(false))
+ if (!cam->set_autoExposure(true))
return {};
- if (!cam->setLaserLevel(1))
+ if (!cam->set_exposureTime(std::chrono::microseconds(30)))
return {};
- if (!cam->setGain(2))
+ if (!cam->set_autoGain(false))
return {};
- if (!cam->setSomething(0)) {
+ if (!cam->set_gain(0.1))
return {};
- }
- // m_someThread = std::jthread{[=](std::stop_token stopToken) {
- // std::cout << "VeyeIMX287m: start stream" << std::endl;
- // sleep(5);
-
- // static int i = 0;
- // while (!stopToken.stop_requested()) {
- // cam->setSomething(i);
- // i -= 1;
- // }
- // }};
+ if (!cam->setLaserLevel(1))
+ return {};
return {cam};
}
@@ -283,8 +271,8 @@ bool VeyeIMX287m::startStream()
auto ret = ioctl(m_cam_fd, VIDIOC_STREAMON, &radxa_buf_type);
if (ret != 0) {
- std::cerr << "ioctl(VIDIOC_STREAMON) failed: " << errno << " (" << strerror(errno) << ")"
- << std::endl;
+ std::cerr << "ioctl(VIDIOC_STREAMON) failed: " << errno << " ("
+ << strerror(errno) << ")" << std::endl;
return false;
}
@@ -310,123 +298,110 @@ bool VeyeIMX287m::init()
if (!initCam())
return false;
+ if (!initI2C()) {
+ return false;
+ }
+
if (!initHttpServer())
return false;
return true;
}
-bool VeyeIMX287m::setExposureTime(const std::chrono::microseconds us)
+bool VeyeIMX287m::set_autoExposure(const bool enable)
{
- const std::string i2c_dev{"/dev/i2c-2"};
- const auto address = 0x3b;
- const auto metime_reg = 0xc10;
- const auto val = us.count();
-
- const int fd = open(i2c_dev.c_str(), O_RDWR);
+ using namespace veye::imx287m;
- if (!fd) {
- std::cerr << "cannot open i2c dev: " << i2c_dev << ", errno: " << errno << " ("
- << strerror(errno) << ")" << std::endl;
- return false;
- }
+ const uint32_t value = static_cast<uint32_t>(
+ enable ? ExposureMode::AutoExposureContinious : ExposureMode::Manual);
- return true;
+ return m_i2c->write(static_cast<uint16_t>(Register::Exposure_Mode), value);
}
-bool VeyeIMX287m::setExposureTimeUs(int valueUs)
+std::optional<bool> VeyeIMX287m::get_autoExposure()
{
- std::cout << "AAAAAAAAAAAAAAAAAAAAAAAAAAAAA: " << __func__ << ": " << valueUs << std::endl;
- const std::string i2c_dev{"/dev/i2c-2"};
- const auto address = 0x3b;
- const auto metime_reg = 0xc10;
+ using namespace veye::imx287m;
- //return true;
- std::cout << __func__ << ": " << V4L2_CID_EXPOSURE << " - " << valueUs << std::endl
- << std::flush;
+ const auto value = m_i2c->read(
+ static_cast<uint32_t>(Register::Exposure_Mode));
- /*
- * Shutter Time. Value is from 8721ns to 8721*885ns, must be integral
- * multiple of 8721ns .
- * 8721xN(N =1,2,3,4,5.....855)
- */
- // constexpr int exposureStep{8721};
- // constexpr int maxExposureStepMultiplier{885};
- // auto valueNs = valueUs;
- // valueNs = (valueNs / exposureStep) * exposureStep;
+ if (!value) {
+ return {};
+ }
- // std::clamp(valueNs, exposureStep, exposureStep * maxExposureStepMultiplier);
- // setGain(rand() % 254);
- // setGain(3);
- // setLaserLevel(rand() % 0x7fffffff);
- // setLaserLevel(rand() % 100);
- // int exp = rand() % 10;
- // return setCamParam(V4L2_CID_EXPOSURE, exp * exp * exp * exp * exp * exp);
- // return setCamParam(V4L2_CID_EXPOSURE, valueUs);
- return setCamParam(V4L2_CID_EXPOSURE, valueUs);
+ return *value
+ == static_cast<uint32_t>(ExposureMode::AutoExposureContinious);
}
-bool VeyeIMX287m::setGain(int value)
+bool VeyeIMX287m::set_autoGain(const bool enable)
{
- std::cout << __func__ << ": " << value << std::endl << std::flush;
+ using namespace veye::imx287m;
- // return setCamParam(V4L2_CID_GAIN, value);
- // FIXME: tmp workaround for imx287llr
- return true;
+ const uint32_t value = static_cast<uint32_t>(
+ enable ? GainMode::AutoGainContinious : GainMode::Manual);
+
+ return m_i2c->write(static_cast<uint16_t>(Register::Gain_Mode), value);
}
-bool VeyeIMX287m::setLaserLevel(int value)
+std::optional<bool> VeyeIMX287m::get_autoGain()
{
- std::cout << __func__ << ": " << value << std::endl << std::flush;
+ using namespace veye::imx287m;
- // return setCamParam(V4L2_CID_FLASH_TIMEOUT, value);
+ const auto value = m_i2c->read(static_cast<uint32_t>(Register::Gain_Mode));
- // FIXME: tmp workaround for imx287llr
- return true;
+ if (!value) {
+ return {};
+ }
+
+ return *value == static_cast<uint32_t>(GainMode::AutoGainContinious);
}
-bool VeyeIMX287m::setSomething(int value)
+bool VeyeIMX287m::set_exposureTime(const std::chrono::microseconds us)
{
- std::cout << __func__ << ": " << value << std::endl << std::flush;
-
- // return setCamParam(V4L2_CID_FLASH_INTENSITY, value);
- // FIXME: tmp workaround for imx287llr
- return true;
+ using namespace veye::imx287m;
+ return m_i2c->write(static_cast<uint16_t>(Register::ME_Time), us.count());
}
-bool VeyeIMX287m::setCamParam(unsigned int v4l2controlId, int value)
+std::optional<const std::chrono::microseconds> VeyeIMX287m::get_exposureTime()
{
- veye::imx287m::test(value);
+ using namespace veye::imx287m;
- std::cout << "radxa: skip setCamParam" << std::endl;
+ const auto value = m_i2c->read(static_cast<uint32_t>(Register::ME_Time));
- return true;
-
- v4l2_control ctl{v4l2controlId, value};
+ if (!value) {
+ return {};
+ }
- if (ioctl(m_cam_fd, VIDIOC_S_CTRL, &ctl) < 0) {
- fprintf(stderr,
- "cannot set cam param: id - %d, error - '%s'\n",
- v4l2controlId,
- strerror(errno));
- fflush(stderr);
+ return std::chrono::microseconds{*value};
+}
- return false;
- }
+bool VeyeIMX287m::set_gain(const float value)
+{
+ using namespace veye::imx287m;
+ return m_i2c->write(static_cast<uint16_t>(Register::Manual_Gain),
+ static_cast<uint32_t>(value * 10));
+}
- if (ioctl(m_cam_fd, VIDIOC_G_CTRL, &ctl) < 0) {
- fprintf(stderr,
- "cannot get cam param: id - %d, error - '%s'\n",
- v4l2controlId,
- strerror(errno));
+std::optional<float> VeyeIMX287m::get_gain()
+{
+ using namespace veye::imx287m;
- fflush(stderr);
+ const auto value = m_i2c->read(static_cast<uint32_t>(Register::Manual_Gain));
- return false;
+ if (!value) {
+ return {};
}
- std::cout << __func__ << ": new value is " << ctl.value << std::endl;
+ return *value * 10;
+}
+
+bool VeyeIMX287m::setLaserLevel(int value)
+{
+ std::cout << __func__ << ": " << value << std::endl << std::flush;
+
+ // return setCamParam(V4L2_CID_FLASH_TIMEOUT, value);
+ // FIXME: tmp workaround for imx287llr
return true;
}
@@ -435,7 +410,10 @@ bool VeyeIMX287m::openCam()
m_cam_fd = open(videoDevice, O_RDWR);
if (m_cam_fd < 0) {
- fprintf(stderr, "cannot open cam '%s', error: '%s'\n", videoDevice, strerror(errno));
+ fprintf(stderr,
+ "cannot open cam '%s', error: '%s'\n",
+ videoDevice,
+ strerror(errno));
return false;
}
@@ -448,7 +426,10 @@ bool VeyeIMX287m::selectCam(int camIdx)
int ret = ioctl(m_cam_fd, VIDIOC_S_INPUT, &input);
if (ret < 0) {
- fprintf(stderr, "cannot select cam: idx - %d, error - '%s'\n", camIdx, strerror(errno));
+ fprintf(stderr,
+ "cannot select cam: idx - %d, error - '%s'\n",
+ camIdx,
+ strerror(errno));
return false;
}
@@ -474,7 +455,9 @@ bool VeyeIMX287m::initCam()
ret = ioctl(m_cam_fd, VIDIOC_TRY_FMT, &format);
if (ret < 0) {
- fprintf(stderr, "cannot try cam format: error - '%s'\n", strerror(errno));
+ fprintf(stderr,
+ "cannot try cam format: error - '%s'\n",
+ strerror(errno));
return false;
}
@@ -485,7 +468,9 @@ bool VeyeIMX287m::initCam()
ret = ioctl(m_cam_fd, VIDIOC_S_FMT, &format);
if (ret < 0) {
- fprintf(stderr, "cannot set cam format: error - '%s'\n", strerror(errno));
+ fprintf(stderr,
+ "cannot set cam format: error - '%s'\n",
+ strerror(errno));
return false;
}
@@ -541,7 +526,9 @@ bool VeyeIMX287m::initCam()
ret = ioctl(m_cam_fd, VIDIOC_REQBUFS, &rb);
if (ret < 0) {
- fprintf(stderr, "cannot set cam request buffers: ioctl error - '%s'\n", strerror(errno));
+ fprintf(stderr,
+ "cannot set cam request buffers: ioctl error - '%s'\n",
+ strerror(errno));
return false;
}
@@ -565,7 +552,8 @@ bool VeyeIMX287m::initCam()
std::cout << "query buffers" << std::endl;
for (uint32_t i = 0; i < rb.count; i++) {
- std::cout << "-----------------------------------------------------" << std::endl;
+ std::cout << "-----------------------------------------------------"
+ << std::endl;
struct v4l2_buffer buf;
struct v4l2_plane planes[VIDEO_MAX_PLANES];
@@ -583,8 +571,8 @@ bool VeyeIMX287m::initCam()
if (ret < 0) {
// std::cout << "ioctl(VIDIOC_QUERYBUF) failed: " << errno << " " << std::endl;
- std::cerr << "ioctl(VIDIOC_QUERYBUF) failed: " << errno << " (" << strerror(errno)
- << ")" << std::endl;
+ std::cerr << "ioctl(VIDIOC_QUERYBUF) failed: " << errno << " ("
+ << strerror(errno) << ")" << std::endl;
return false;
}
@@ -597,9 +585,15 @@ bool VeyeIMX287m::initCam()
const auto length = buf.m.planes[0].length;
const auto offset = buf.m.planes[0].m.mem_offset;
- buffers[i].mem[0] = mmap(0, length, PROT_READ | PROT_WRITE, MAP_SHARED, m_cam_fd, offset);
+ buffers[i].mem[0] = mmap(0,
+ length,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ m_cam_fd,
+ offset);
if (buffers[i].mem[0] == MAP_FAILED) {
- std::cerr << "mmap() failed: " << errno << " (" << strerror(errno) << ")" << std::endl;
+ std::cerr << "mmap() failed: " << errno << " (" << strerror(errno)
+ << ")" << std::endl;
std::cerr << "length: " << length << std::endl;
std::cerr << "offset: " << offset << std::endl;
return false;
@@ -616,15 +610,18 @@ bool VeyeIMX287m::initCam()
buffers[i].size[i] = length;
buffers[i].padding[i] = 0;
- printf("Buffer %u/%u mapped at address %p.\n", buffers[i].idx, i, buffers[i].mem[0]);
+ printf("Buffer %u/%u mapped at address %p.\n",
+ buffers[i].idx,
+ i,
+ buffers[i].mem[0]);
// buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
// buf.memory = V4L2_MEMORY_MMAP;
// buf.index = i;
ret = ioctl(m_cam_fd, VIDIOC_QBUF, &buf);
if (ret != 0) {
- std::cerr << "ioctl(VIDIOC_QBUF) failed: " << errno << " (" << strerror(errno) << ")"
- << std::endl;
+ std::cerr << "ioctl(VIDIOC_QBUF) failed: " << errno << " ("
+ << strerror(errno) << ")" << std::endl;
return false;
}
@@ -650,6 +647,13 @@ bool VeyeIMX287m::initCam()
return true;
}
+bool VeyeIMX287m::initI2C()
+{
+ m_i2c = std::make_shared<veye::imx287m::i2c>();
+
+ return m_i2c != nullptr && m_i2c->open();
+}
+
bool VeyeIMX287m::initHttpServer()
{
m_httpServer = std::make_shared<HttpServer>(this);
@@ -761,8 +765,8 @@ bool VeyeIMX287m::dequeueImageBuffer(size_t &imageIndex)
}
if (ret != 0) {
- std::cerr << "ioctl(VIDIOC_DQBUF) failed: " << errno << " (" << strerror(errno) << ")"
- << std::endl;
+ std::cerr << "ioctl(VIDIOC_DQBUF) failed: " << errno << " ("
+ << strerror(errno) << ")" << std::endl;
return false;
}
@@ -780,11 +784,13 @@ bool VeyeIMX287m::dequeueImageBuffer(size_t &imageIndex)
// image.counters.encoderPosition = RotaryEncoder::instance()->position();
image.counters.measurementCounter = buf.sequence;
+ // FIXME: git rid of static vars
static int64_t prevCounter = buf.sequence;
dropped_count += buf.sequence - prevCounter - 1;
prevCounter = buf.sequence;
- image.counters.timestampUs = buf.timestamp.tv_sec * 1000 * 1000 + buf.timestamp.tv_usec;
+ image.counters.timestampUs = buf.timestamp.tv_sec * 1000 * 1000
+ + buf.timestamp.tv_usec;
{
std::lock_guard<std::mutex> lock(m_camMtx);
@@ -792,8 +798,8 @@ bool VeyeIMX287m::dequeueImageBuffer(size_t &imageIndex)
}
if (ret != 0) {
- std::cerr << "ioctl(VIDIOC_QBUF) failed: " << errno << " (" << strerror(errno) << ")"
- << std::endl;
+ std::cerr << "ioctl(VIDIOC_QBUF) failed: " << errno << " ("
+ << strerror(errno) << ")" << std::endl;
return false;
}
diff --git a/src/camera/veyeimx287m.h b/src/camera/veyeimx287m.h
index 7d7e2c6..d8c42ae 100644
--- a/src/camera/veyeimx287m.h
+++ b/src/camera/veyeimx287m.h
@@ -10,6 +10,12 @@
#include "icamera.h"
+namespace veye {
+namespace imx287m {
+class i2c;
+} // namespace imx287m
+} // namespace veye
+
class HttpServer;
class VeyeIMX287m : public ICamera
@@ -29,18 +35,26 @@ public:
public:
bool startStream() override;
+ bool dequeueImageBuffer(size_t &image);
+ bool getImage(Image &image);
+
bool init();
- bool setExposureTime(const std::chrono::microseconds us);
- bool setExposureTimeUs(int value) override;
- bool setGain(int value) override;
+ // parameters
+public:
+ bool set_autoExposure(const bool enable) override;
+ std::optional<bool> get_autoExposure() override;
- bool setLaserLevel(int value) override;
+ bool set_autoGain(const bool enable) override;
+ std::optional<bool> get_autoGain() override;
- bool setSomething(int value) override;
+ bool set_exposureTime(const std::chrono::microseconds us) override;
+ std::optional<const std::chrono::microseconds> get_exposureTime() override;
- bool dequeueImageBuffer(size_t &image);
- bool getImage(Image &image);
+ bool set_gain(const float value) override;
+ std::optional<float> get_gain() override;
+
+ bool setLaserLevel(int value) override;
public:
/*!
@@ -50,10 +64,11 @@ public:
uint32_t processedCounter{0};
private:
- bool setCamParam(unsigned int v4l2controlId, int value);
bool openCam();
bool selectCam(int camIdx = 0);
bool initCam();
+
+ bool initI2C();
bool initHttpServer();
void calcFrameLoop(std::stop_token stopToken);
@@ -95,5 +110,6 @@ private:
// std::jthread m_calcThreads[1];
std::jthread m_calcThreads[4];
+ std::shared_ptr<veye::imx287m::i2c> m_i2c;
std::shared_ptr<HttpServer> m_httpServer;
};
diff --git a/src/camera/veyeimx287m_types.h b/src/camera/veyeimx287m_types.h
index 640a0e1..8cb74ba 100644
--- a/src/camera/veyeimx287m_types.h
+++ b/src/camera/veyeimx287m_types.h
@@ -5,7 +5,7 @@
namespace veye {
namespace imx287m {
-enum class Register {
+enum class Register : uint16_t {
ImageAcqu = 0x0400,
ImageFeature = 0x0800,
ImageSigProc = 0x0c00,
@@ -126,6 +126,18 @@ enum class Register {
GPIO2_Reverse = 0x1038
};
+enum class ExposureMode : uint32_t {
+ Manual = 0,
+ AutoExposureOnce = 1,
+ AutoExposureContinious = 2
+};
+
+enum class GainMode : uint32_t {
+ Manual = 0,
+ AutoGainOnce = 1,
+ AutoGainContinious = 2
+};
+
class Params : public QObject
{
// Q_OBJECT