1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (C) 2019, Raspberry Pi (Trading) Limited
*
* cam_helper_imx219.cpp - camera helper for imx219 sensor
*/
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
/*
* We have observed that the imx219 embedded data stream randomly returns junk
* register values. Do not rely on embedded data until this has been resolved.
*/
#define ENABLE_EMBEDDED_DATA 0
#include "cam_helper.hpp"
#if ENABLE_EMBEDDED_DATA
#include "md_parser.hpp"
#endif
using namespace RPiController;
/*
* We care about one gain register and a pair of exposure registers. Their I2C
* addresses from the Sony IMX219 datasheet:
*/
constexpr uint32_t gainReg = 0x157;
constexpr uint32_t expHiReg = 0x15a;
constexpr uint32_t expLoReg = 0x15b;
constexpr uint32_t frameLengthHiReg = 0x160;
constexpr uint32_t frameLengthLoReg = 0x161;
constexpr std::initializer_list<uint32_t> registerList [[maybe_unused]]
= { expHiReg, expLoReg, gainReg, frameLengthHiReg, frameLengthLoReg };
class CamHelperImx219 : public CamHelper
{
public:
CamHelperImx219();
uint32_t GainCode(double gain) const override;
double Gain(uint32_t gain_code) const override;
unsigned int MistrustFramesModeSwitch() const override;
bool SensorEmbeddedDataPresent() const override;
private:
/*
* Smallest difference between the frame length and integration time,
* in units of lines.
*/
static constexpr int frameIntegrationDiff = 4;
void PopulateMetadata(const MdParser::RegisterMap ®isters,
Metadata &metadata) const override;
};
CamHelperImx219::CamHelperImx219()
#if ENABLE_EMBEDDED_DATA
: CamHelper(std::make_unique<MdParserSmia>(registerList), frameIntegrationDiff)
#else
: CamHelper({}, frameIntegrationDiff)
#endif
{
}
uint32_t CamHelperImx219::GainCode(double gain) const
{
return (uint32_t)(256 - 256 / gain);
}
double CamHelperImx219::Gain(uint32_t gain_code) const
{
return 256.0 / (256 - gain_code);
}
unsigned int CamHelperImx219::MistrustFramesModeSwitch() const
{
/*
* For reasons unknown, we do occasionally get a bogus metadata frame
* at a mode switch (though not at start-up). Possibly warrants some
* investigation, though not a big deal.
*/
return 1;
}
bool CamHelperImx219::SensorEmbeddedDataPresent() const
{
return ENABLE_EMBEDDED_DATA;
}
void CamHelperImx219::PopulateMetadata(const MdParser::RegisterMap ®isters,
Metadata &metadata) const
{
DeviceStatus deviceStatus;
deviceStatus.shutter_speed = Exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg));
deviceStatus.analogue_gain = Gain(registers.at(gainReg));
deviceStatus.frame_length = registers.at(frameLengthHiReg) * 256 + registers.at(frameLengthLoReg);
metadata.Set("device.status", deviceStatus);
}
static CamHelper *Create()
{
return new CamHelperImx219();
}
static RegisterCamHelper reg("imx219", &Create);
|