You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							136 lines
						
					
					
						
							7.1 KiB
						
					
					
				
			
		
		
	
	
							136 lines
						
					
					
						
							7.1 KiB
						
					
					
				| #include <cassert>
 | |
| #include <cmath>
 | |
| 
 | |
| #include "system/camerad/sensors/sensor.h"
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| const size_t AR0231_REGISTERS_HEIGHT = 2;
 | |
| // TODO: this extra height is universal and doesn't apply per camera
 | |
| const size_t AR0231_STATS_HEIGHT = 2 + 8;
 | |
| 
 | |
| const float sensor_analog_gains_AR0231[] = {
 | |
|     1.0 / 8.0, 2.0 / 8.0, 2.0 / 7.0, 3.0 / 7.0,  // 0, 1, 2, 3
 | |
|     3.0 / 6.0, 4.0 / 6.0, 4.0 / 5.0, 5.0 / 5.0,  // 4, 5, 6, 7
 | |
|     5.0 / 4.0, 6.0 / 4.0, 6.0 / 3.0, 7.0 / 3.0,  // 8, 9, 10, 11
 | |
|     7.0 / 2.0, 8.0 / 2.0, 8.0 / 1.0};            // 12, 13, 14, 15 = bypass
 | |
| 
 | |
| }  // namespace
 | |
| 
 | |
| AR0231::AR0231() {
 | |
|   image_sensor = cereal::FrameData::ImageSensor::AR0231;
 | |
|   bayer_pattern = CAM_ISP_PATTERN_BAYER_GRGRGR;
 | |
|   pixel_size_mm = 0.003;
 | |
|   data_word = true;
 | |
|   frame_width = 1928;
 | |
|   frame_height = 1208;
 | |
|   frame_stride = (frame_width * 12 / 8) + 4;
 | |
|   extra_height = AR0231_REGISTERS_HEIGHT + AR0231_STATS_HEIGHT;
 | |
| 
 | |
|   registers_offset = 0;
 | |
|   frame_offset = AR0231_REGISTERS_HEIGHT;
 | |
|   stats_offset = AR0231_REGISTERS_HEIGHT + frame_height;
 | |
| 
 | |
|   start_reg_array.assign(std::begin(start_reg_array_ar0231), std::end(start_reg_array_ar0231));
 | |
|   init_reg_array.assign(std::begin(init_array_ar0231), std::end(init_array_ar0231));
 | |
|   probe_reg_addr = 0x3000;
 | |
|   probe_expected_data = 0x354;
 | |
|   bits_per_pixel = 12;
 | |
|   mipi_format = CAM_FORMAT_MIPI_RAW_12;
 | |
|   frame_data_type = 0x12;  // Changing stats to 0x2C doesn't work, so change pixels to 0x12 instead
 | |
|   mclk_frequency = 19200000; //Hz
 | |
| 
 | |
|   readout_time_ns = 22850000;
 | |
| 
 | |
|   dc_gain_factor = 2.5;
 | |
|   dc_gain_min_weight = 0;
 | |
|   dc_gain_max_weight = 1;
 | |
|   dc_gain_on_grey = 0.2;
 | |
|   dc_gain_off_grey = 0.3;
 | |
|   exposure_time_min = 2;       // with HDR, fastest ss
 | |
|   exposure_time_max = 0x0855;  // with HDR, slowest ss, 40ms
 | |
|   analog_gain_min_idx = 0x1;   // 0.25x
 | |
|   analog_gain_rec_idx = 0x6;   // 0.8x
 | |
|   analog_gain_max_idx = 0xD;   // 4.0x
 | |
|   analog_gain_cost_delta = 0;
 | |
|   analog_gain_cost_low = 0.1;
 | |
|   analog_gain_cost_high = 5.0;
 | |
|   for (int i = 0; i <= analog_gain_max_idx; i++) {
 | |
|     sensor_analog_gains[i] = sensor_analog_gains_AR0231[i];
 | |
|   }
 | |
|   min_ev = exposure_time_min * sensor_analog_gains[analog_gain_min_idx];
 | |
|   max_ev = exposure_time_max * dc_gain_factor * sensor_analog_gains[analog_gain_max_idx];
 | |
|   target_grey_factor = 1.0;
 | |
| 
 | |
|   black_level = 168;
 | |
|   color_correct_matrix = {
 | |
|     0x000000af, 0x00000ff9, 0x00000fd8,
 | |
|     0x00000fbc, 0x000000bb, 0x00000009,
 | |
|     0x00000fb6, 0x00000fe0, 0x000000ea,
 | |
|   };
 | |
|   for (int i = 0; i < 65; i++) {
 | |
|     float fx = i / 64.0;
 | |
|     const float gamma_k = 0.75;
 | |
|     const float gamma_b = 0.125;
 | |
|     const float mp = 0.01; // ideally midpoint should be adaptive
 | |
|     const float rk = 9 - 100*mp;
 | |
|     // poly approximation for s curve
 | |
|     fx = (fx > mp) ?
 | |
|       ((rk * (fx-mp) * (1-(gamma_k*mp+gamma_b)) * (1+1/(rk*(1-mp))) / (1+rk*(fx-mp))) + gamma_k*mp + gamma_b) :
 | |
|       ((rk * (fx-mp) * (gamma_k*mp+gamma_b) * (1+1/(rk*mp)) / (1-rk*(fx-mp))) + gamma_k*mp + gamma_b);
 | |
|     gamma_lut_rgb.push_back((uint32_t)(fx*1023.0 + 0.5));
 | |
|   }
 | |
|   prepare_gamma_lut();
 | |
|   linearization_lut = {
 | |
|     0x02000000, 0x02000000, 0x02000000, 0x02000000,
 | |
|     0x020007ff, 0x020007ff, 0x020007ff, 0x020007ff,
 | |
|     0x02000bff, 0x02000bff, 0x02000bff, 0x02000bff,
 | |
|     0x020017ff, 0x020017ff, 0x020017ff, 0x020017ff,
 | |
|     0x02001bff, 0x02001bff, 0x02001bff, 0x02001bff,
 | |
|     0x020023ff, 0x020023ff, 0x020023ff, 0x020023ff,
 | |
|     0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff,
 | |
|     0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff,
 | |
|     0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff,
 | |
|   };
 | |
|   linearization_pts = {0x07ff0bff, 0x17ff1bff, 0x23ff3fff, 0x3fff3fff};
 | |
|   vignetting_lut = {
 | |
|     0x00eaa755, 0x00cf2679, 0x00bc05e0, 0x00acc566, 0x00a1450a, 0x009984cc, 0x0095a4ad, 0x009584ac, 0x009944ca, 0x00a0c506, 0x00ac0560, 0x00bb25d9, 0x00ce2671, 0x00e90748, 0x01112889, 0x014a2a51, 0x01984cc2,
 | |
|     0x00db06d8, 0x00c30618, 0x00afe57f, 0x00a0a505, 0x009524a9, 0x008d646b, 0x0089844c, 0x0089644b, 0x008d2469, 0x0094a4a5, 0x009fe4ff, 0x00af0578, 0x00c20610, 0x00d986cc, 0x00fda7ed, 0x01320990, 0x017aebd7,
 | |
|     0x00d1868c, 0x00baa5d5, 0x00a7853c, 0x009844c2, 0x008cc466, 0x0085a42d, 0x0083641b, 0x0083641b, 0x0085842c, 0x008c4462, 0x0097a4bd, 0x00a6c536, 0x00b9a5cd, 0x00d06683, 0x00f1678b, 0x01226913, 0x0167ab3d,
 | |
|     0x00cd0668, 0x00b625b1, 0x00a30518, 0x0093c49e, 0x00884442, 0x00830418, 0x0080e407, 0x0080c406, 0x0082e417, 0x0087c43e, 0x00932499, 0x00a22511, 0x00b525a9, 0x00cbe65f, 0x00eb0758, 0x011a68d3, 0x015daaed,
 | |
|     0x00cc4662, 0x00b565ab, 0x00a24512, 0x00930498, 0x0087843c, 0x0082a415, 0x00806403, 0x00806403, 0x00828414, 0x00870438, 0x00926493, 0x00a1850c, 0x00b465a3, 0x00cb2659, 0x00ea2751, 0x011928c9, 0x015c2ae1,
 | |
|     0x00cf667b, 0x00b885c4, 0x00a5652b, 0x009624b1, 0x008aa455, 0x00846423, 0x00822411, 0x00822411, 0x00844422, 0x008a2451, 0x009564ab, 0x00a48524, 0x00b785bc, 0x00ce4672, 0x00ee6773, 0x011e88f4, 0x0162eb17,
 | |
|     0x00d6c6b6, 0x00bf65fb, 0x00ac4562, 0x009d04e8, 0x0091848c, 0x0089c44e, 0x00862431, 0x00860430, 0x0089844c, 0x00910488, 0x009c64e3, 0x00ab655b, 0x00be65f3, 0x00d566ab, 0x00f847c2, 0x012b2959, 0x01726b93,
 | |
|     0x00e3e71f, 0x00ca0650, 0x00b705b8, 0x00a7a53d, 0x009c24e1, 0x009484a4, 0x00908484, 0x00908484, 0x009424a1, 0x009bc4de, 0x00a70538, 0x00b625b1, 0x00c90648, 0x00e26713, 0x0108e847, 0x013fe9ff, 0x018bcc5e,
 | |
|     0x00f807c0, 0x00d966cb, 0x00c5862c, 0x00b625b1, 0x00aaa555, 0x00a30518, 0x009f04f8, 0x009f04f8, 0x00a2a515, 0x00aa2551, 0x00b585ac, 0x00c4a625, 0x00d846c2, 0x00f647b2, 0x0121a90d, 0x015e4af2, 0x01b8cdc6,
 | |
|     0x011548aa, 0x00f1678b, 0x00d886c4, 0x00c86643, 0x00bce5e7, 0x00b545aa, 0x00b1658b, 0x00b1458a, 0x00b505a8, 0x00bc85e4, 0x00c7c63e, 0x00d786bc, 0x00efe77f, 0x0113489a, 0x0144ea27, 0x01888c44, 0x01fdcfee,
 | |
|     0x013e49f2, 0x0113e89f, 0x00f5a7ad, 0x00e0c706, 0x00d30698, 0x00cb665b, 0x00c7663b, 0x00c7663b, 0x00cb0658, 0x00d2a695, 0x00dfe6ff, 0x00f467a3, 0x01122891, 0x013be9df, 0x01750ba8, 0x01cfae7d, 0x025912c8,
 | |
|     0x01766bb3, 0x01446a23, 0x011fc8fe, 0x0105e82f, 0x00f467a3, 0x00e9874c, 0x00e46723, 0x00e44722, 0x00e92749, 0x00f3a79d, 0x0104c826, 0x011e48f2, 0x01424a12, 0x01738b9c, 0x01bf6dfb, 0x023611b0, 0x02ced676,
 | |
|     0x01cf8e7c, 0x01866c33, 0x015aaad5, 0x013ae9d7, 0x01250928, 0x011768bb, 0x0110a885, 0x01108884, 0x0116e8b7, 0x01242921, 0x0139a9cd, 0x0158eac7, 0x01840c20, 0x01cb0e58, 0x0233719b, 0x02b9d5ce, 0x03645b22,
 | |
|   };
 | |
| }
 | |
| 
 | |
| std::vector<i2c_random_wr_payload> AR0231::getExposureRegisters(int exposure_time, int new_exp_g, bool dc_gain_enabled) const {
 | |
|   uint16_t analog_gain_reg = 0xFF00 | (new_exp_g << 4) | new_exp_g;
 | |
|   return {
 | |
|     {0x3366, analog_gain_reg},
 | |
|     {0x3362, (uint16_t)(dc_gain_enabled ? 0x1 : 0x0)},
 | |
|     {0x3012, (uint16_t)exposure_time},
 | |
|   };
 | |
| }
 | |
| 
 | |
| int AR0231::getSlaveAddress(int port) const {
 | |
|   assert(port >= 0 && port <= 2);
 | |
|   return (int[]){0x20, 0x30, 0x20}[port];
 | |
| }
 | |
| 
 | |
| float AR0231::getExposureScore(float desired_ev, int exp_t, int exp_g_idx, float exp_gain, int gain_idx) const {
 | |
|   // Cost of ev diff
 | |
|   float score = std::abs(desired_ev - (exp_t * exp_gain)) * 10;
 | |
|   // Cost of absolute gain
 | |
|   float m = exp_g_idx > analog_gain_rec_idx ? analog_gain_cost_high : analog_gain_cost_low;
 | |
|   score += std::abs(exp_g_idx - (int)analog_gain_rec_idx) * m;
 | |
|   // Cost of changing gain
 | |
|   score += std::abs(exp_g_idx - gain_idx) * (score + 1.0) / 10.0;
 | |
|   return score;
 | |
| }
 | |
| 
 |