<div dir="ltr"><div dir="ltr">Hi Laurent,<div><br></div><div>Thank you for your work.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, 19 Dec 2021 at 23:27, Laurent Pinchart <<a href="mailto:laurent.pinchart@ideasonboard.com">laurent.pinchart@ideasonboard.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">From: Naushir Patuck <<a href="mailto:naush@raspberrypi.com" target="_blank">naush@raspberrypi.com</a>><br>
<br>
The Sony IMX296 sensor has an exponential gain model, and adds a fixed<br>
14.26µs offset to the exposure time expressed in line units.<br>
<br>
Signed-off-by: Laurent Pinchart <<a href="mailto:laurent.pinchart@ideasonboard.com" target="_blank">laurent.pinchart@ideasonboard.com</a>><br>
---<br>
src/ipa/raspberrypi/cam_helper_imx296.cpp | 126 ++++++++++++++++++++++<br>
src/ipa/raspberrypi/meson.build | 1 +<br>
2 files changed, 127 insertions(+)<br>
create mode 100644 src/ipa/raspberrypi/cam_helper_imx296.cpp<br>
<br>
diff --git a/src/ipa/raspberrypi/cam_helper_imx296.cpp b/src/ipa/raspberrypi/cam_helper_imx296.cpp<br>
new file mode 100644<br>
index 000000000000..9c34582861f1<br>
--- /dev/null<br>
+++ b/src/ipa/raspberrypi/cam_helper_imx296.cpp<br>
@@ -0,0 +1,126 @@<br>
+/* SPDX-License-Identifier: BSD-2-Clause */<br>
+/*<br>
+ * Copyright (C) 2020, Raspberry Pi (Trading) Limited<br>
+ *<br>
+ * cam_helper_imx296.cpp - camera helper for imx296 sensor<br>
+ */<br>
+<br>
+#include <assert.h><br>
+#include <cmath><br>
+#include <stddef.h><br>
+#include <stdio.h><br>
+#include <stdlib.h><br>
+<br>
+/*<br>
+ * We have observed the imx296 embedded data stream randomly return junk<br>
+ * reister values. Do not rely on embedded data until this has been resolved.<br>
+ */<br>
+#define ENABLE_EMBEDDED_DATA 0<br></blockquote><div><br></div><div>I'm afraid this may not be completely true :-)</div><div><br></div><div>This file was created by doing a search/replace from the imx219 cam helper.</div><div>Perhaps it might be better to completely remove embedded data support</div><div>until we have a chance to properly evaluate this functionality on the imx296?</div><div><br></div><div>Either way,</div><div><br></div><div><div>Signed-off-by: Naushir Patuck <<a href="mailto:naushir@gmail.com" target="_blank">naush</a>@<a href="http://raspberrypi.com">raspberrypi.com</a>><br></div><div>Reviewed-by: Naushir Patuck <<a href="mailto:naushir@gmail.com" target="_blank">naush</a>@<a href="http://raspberrypi.com">raspberrypi.com</a>></div></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+#include "cam_helper.hpp"<br>
+#if ENABLE_EMBEDDED_DATA<br>
+#include "md_parser.hpp"<br>
+#endif<br>
+<br>
+//#include "imx296_gain_table.hpp"<br>
+<br>
+using namespace RPiController;<br>
+using libcamera::utils::Duration;<br>
+using namespace std::literals::chrono_literals;<br>
+<br>
+/*<br>
+ * We care about one gain register and a pair of exposure registers. Their I2C<br>
+ * addresses from the Sony IMX296 datasheet:<br>
+ */<br>
+constexpr uint32_t gainReg = 0x157;<br>
+constexpr uint32_t expHiReg = 0x15a;<br>
+constexpr uint32_t expLoReg = 0x15b;<br>
+constexpr std::initializer_list<uint32_t> registerList [[maybe_unused]] = { expHiReg, expLoReg, gainReg };<br>
+<br>
+class CamHelperImx296 : public CamHelper<br>
+{<br>
+public:<br>
+ CamHelperImx296();<br>
+ uint32_t GainCode(double gain) const override;<br>
+ double Gain(uint32_t gain_code) const override;<br>
+ uint32_t ExposureLines(Duration exposure) const override;<br>
+ Duration Exposure(uint32_t exposure_lines) const override;<br>
+ unsigned int MistrustFramesModeSwitch() const override;<br>
+ bool SensorEmbeddedDataPresent() const override;<br>
+<br>
+private:<br>
+ static constexpr uint32_t maxGainCode = 239;<br>
+ static constexpr Duration timePerLine = 550.0 / 37.125e6 * 1.0s;<br>
+<br>
+ /*<br>
+ * Smallest difference between the frame length and integration time,<br>
+ * in units of lines.<br>
+ */<br>
+ static constexpr int frameIntegrationDiff = 4;<br>
+<br>
+ void PopulateMetadata(const MdParser::RegisterMap ®isters,<br>
+ Metadata &metadata) const override;<br>
+};<br>
+<br>
+CamHelperImx296::CamHelperImx296()<br>
+#if ENABLE_EMBEDDED_DATA<br>
+ : CamHelper(std::make_unique<MdParserSmia>(registerList), frameIntegrationDiff)<br>
+#else<br>
+ : CamHelper(nullptr, frameIntegrationDiff)<br>
+#endif<br>
+{<br>
+}<br>
+<br>
+uint32_t CamHelperImx296::GainCode(double gain) const<br>
+{<br>
+ uint32_t code = 20 * std::log10(gain) * 10;<br>
+ return std::min(code, maxGainCode);<br>
+}<br>
+<br>
+double CamHelperImx296::Gain(uint32_t gain_code) const<br>
+{<br>
+ return std::pow(10.0, gain_code / 200.0);<br>
+}<br>
+<br>
+uint32_t CamHelperImx296::ExposureLines(Duration exposure) const<br>
+{<br>
+ return (exposure - 14.26us) / timePerLine;<br>
+}<br>
+<br>
+Duration CamHelperImx296::Exposure(uint32_t exposure_lines) const<br>
+{<br>
+ return exposure_lines * timePerLine + 14.26us;<br>
+}<br>
+<br>
+unsigned int CamHelperImx296::MistrustFramesModeSwitch() const<br>
+{<br>
+ /*<br>
+ * For reasons unknown, we do occasionally get a bogus metadata frame<br>
+ * at a mode switch (though not at start-up). Possibly warrants some<br>
+ * investigation, though not a big deal.<br>
+ */<br>
+ return 1;<br></blockquote><div><br></div><div>This may also be something to evaluate (assuming metadata gets enabled).</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+}<br>
+<br>
+bool CamHelperImx296::SensorEmbeddedDataPresent() const<br>
+{<br>
+ return ENABLE_EMBEDDED_DATA;<br>
+}<br>
+<br>
+void CamHelperImx296::PopulateMetadata(const MdParser::RegisterMap ®isters,<br>
+ Metadata &metadata) const<br>
+{<br>
+ DeviceStatus deviceStatus;<br>
+<br>
+ deviceStatus.shutter_speed = Exposure(<a href="http://registers.at" rel="noreferrer" target="_blank">registers.at</a>(expHiReg) * 256 + <a href="http://registers.at" rel="noreferrer" target="_blank">registers.at</a>(expLoReg));<br>
+ deviceStatus.analogue_gain = Gain(<a href="http://registers.at" rel="noreferrer" target="_blank">registers.at</a>(gainReg));<br>
+<br>
+ metadata.Set("device.status", deviceStatus);<br>
+}<br>
+<br>
+static CamHelper *Create()<br>
+{<br>
+ return new CamHelperImx296();<br>
+}<br>
+<br>
+static RegisterCamHelper reg("imx296", &Create);<br>
diff --git a/src/ipa/raspberrypi/meson.build b/src/ipa/raspberrypi/meson.build<br>
index 176055f42248..32897e07dad9 100644<br>
--- a/src/ipa/raspberrypi/meson.build<br>
+++ b/src/ipa/raspberrypi/meson.build<br>
@@ -21,6 +21,7 @@ rpi_ipa_sources = files([<br>
'cam_helper_ov5647.cpp',<br>
'cam_helper_imx219.cpp',<br>
'cam_helper_imx290.cpp',<br>
+ 'cam_helper_imx296.cpp',<br>
'cam_helper_imx477.cpp',<br>
'cam_helper_imx519.cpp',<br>
'cam_helper_ov9281.cpp',<br>
-- <br>
Regards,<br>
<br>
Laurent Pinchart<br>
<br>
</blockquote></div></div>