# ISP - OTP 功能

## 功能描述

每颗图像传感器和镜头都会有微小的光学/色彩差异，若使用统一算法参数，成像色彩或亮度可能偏移。OTP（One-Time Programmable） 是指“一次性可编程存储区”，目前X5支持AWB 与 LSC 的 OTP功能，将每颗摄像头模组在出厂时的白平衡校准数据与镜头校正数据写入sensor eeprom区域，以便后续设备自动读取、实现符合预期的图像效果。

## 通路介绍

![ 通路 ](./media/13-otp_pipeline.jpg)

注：当前LSC OTP方案对于sensor驱动中写入的golden数据建议覆盖同一模组厂同一规格模组样本。

## LSC OTP

### 准备工作

#### Golden模组挑选

由模组厂按客户需求挑选

#### Golden模组ISP效果调试

在与客户确认的周期内完成Golden模组的ISP效果调试，参照ISP调试流程指导。

### 数据标定

#### 标定环境

Golden模组和Random模组的标定环境一致，可参照下表配置

|      名称       |                            参数                            |                            备注                            |
| :-------------: | :--------------------------------------------------------: | :--------------------------------------------------------: |
|    Gain设置     |           Digital   Gain： 1x；Analog Gain:  1x            |                             -                              |
| Mirror/Flip设置 |                    Mirror OFF; Flip OFF                    |                             -                              |
|     WB设置      |                            OFF                             |                             -                              |
|     PD设置      |                            OFF                             |                             -                              |
|       DPC       |                            OFF                             |                  拍图标定时不需要设置DPC                   |
|    Raw图格式    |                           Raw10                            |                             -                              |
|    图像尺寸     |                        常规尺寸均可                        |                      不支持尺寸为奇数                      |
|     G值要求     | 对于10bit RAW数据，G值推荐在扣除完BLC之后，在400-650左右。 |                             -                              |
|     G值分布     |              中心  （1/5 width * 1/5 Height）              |                  对于G值有要求的区域位置                   |
|  模组管控要求   |            扣除BLC, G值中心亮度/G值边缘亮度 < 5            | LSC支持最大16x Gain下发，但衰减过大易出现shading或块效应。 |
|    推荐色温     |                           5000K                            |         radom与golden模组需在相同色温下拍摄raw数据         |


#### 标定流程

1. 将模组置于光源前1cm以内，调整模组方向使模组镜头的光轴垂直于光源平面，若使用积分球光源则保证模组镜头能通过窗口完全置于积分球内。
2. 参照3.1节表格要求设置模组，调节光源功率使成像中心区域扣除BLC之后的G值调整到400-650左右，拍摄RAW图。
3. 将拍摄的Raw图导入OTP tool，会计算获得17\*17和33\*33的 LSC_table 数据，对Random样件，将生成的17\*17 LSC_table写入EEPROM；对Golden样件，需要将33\*33的LSC_table，写入到sensor驱动中。数据生成示例请见第5节。
4. 以上步骤完成后，请图像调试工程师确认画面表现是否符合预期，若符合预期再进行批量烧录，完成OTP标定。


### OTP数据生成工具
数据生成工具分为两种形式，一种以c与静态库的形式提供，需要修改c代码中的参数后重新编译。另一种将其中的参数以读取文本的形式解析出来，无需再次编译，只需要修改“otp_data.txt”文件中的参数即可。


#### 不需要编译

将raw图命名为“otp.raw”，并修改“otp_data.txt”中的参数。完成后直接运行exe执行文件即可。

**参数说明**

![ 参数说明 ](./media/13-lsc_param.png)

ct_correct_flag：
是否使能色温校正功能，如使用这个功能，需要在otp.raw的同级目录放入std_lsc_otp_1.raw ~ std_lsc_otp_5.raw  ext_lsc_otp_1.raw ~ ext_lsc_otp_5.raw这十张raw数据。
std_lsc_otp_x.raw为与sensor drv中Golden数据一致色温下拍摄的5张随机raw数据。
ext_lsc_otp_x.raw为实际sensor生产产线上，对应色温下拍摄的5张随机raw数据。此时sensor eeprom中烧录的为对应色温下的otp数据。
两条产线使用的5张随机raw需要使用5颗相同的sensor，相同sensor的序号需要一一对应。


**标定两条产线差异功能说明**

模组厂存在多条产线时，若不同产线之间标定所使用的色温存在偏差。比如对于A光，一个是3000K一个是2800K，这样就会导致同一个模组，在不同光源下烧录 otp 的时候烧录值会有些差异，最终导致LSC结果存在偏差。可以挑选5个随机模组，用于计算两条产线间的差异。

![ 色温偏差 ](./media/13-ct_correct.png)

标定步骤：
1. 挑选5个随机模组。
2. 在产线A（以产线A为标准）的色温下，拍摄获得5张raw数据，分别命名成std_lsc_otp_1.raw ~ std_lsc_otp_5.raw。
3. 在产线B的色温下，拍摄同样的5个模组获得5张raw数据，分别命名成ext_lsc_otp_1.raw ~ ext_lsc_otp_5.raw。
4. 之后在对产线B的某一Random模组使用工具生成OTP参数时，可以将ct_correct_flag配置成1，这样工具会自动将两条产线的差异apply到OTP参数上。

例：在使用工具生成产线B的参数时，假设标定Golden对应的色温为TL84。需要分别在产线A和产线B上，色温为TL84下拍摄5个随机模组，命名对应的文件名放到与工具同级目录下，然后ct_correct_flag配置成1即可。

注意：
1. 如果是换成另一产线则需要按照同样的方法再次标定。
2. 5个随机模组需要尽量贴近要校正的模组，当差异过大（例如光学中心位置偏移过大）时，校正的数据会也与理想数据存在较大偏差。


#### 需要编译

OTP tool目前支持windows平台和Linux平台的编译生成。不建议通过这种方式。


### 生成数据结果

数据保存在txt文件中，前一部分为生成数据的一些参数，后面会有四个17\*17和四个33\*33的数据矩阵，分别表示4个通道的矩阵。Random模组生成的17\*17数据作为OTP数据写入EEPROM中，Golden模组生成的33\*33数据写到sensor驱动中。


### sensor驱动示例代码

在sensor初始化时刻，按照以下参考代码，调用对应的接口即可实现OTP功能的设置。

```c

#ifdef OTP_EN
        {
                int32_t rett = 0;
                int32_t v,h;
                sensor_otp_t pdata = {0};
                uint16_t r_matrix[17*17] = R_CHN_MATRIX;
                uint16_t gr_matrix[17*17] = GR_CHN_MATRIX;
                uint16_t gb_matrix[17*17] = GB_CHN_MATRIX;
                uint16_t b_matrix[17*17] = B_CHN_MATRIX;
                uint16_t golden_r_matrix[33*33] = R_GOLDEN_MATRIX;
                uint16_t golden_gr_matrix[33*33] = GR_GOLDEN_MATRIX;
                uint16_t golden_gb_matrix[33*33] = GB_GOLDEN_MATRIX;
                uint16_t golden_b_matrix[33*33] = B_GOLDEN_MATRIX;

                pdata.otp_lsc_enable = 1;
                // 目前仅支持设置成 1
                pdata.lsc_ct_num = 1;

                for (v = 0; v < SENSOR_OTP_LSC_EEPROM_SIZE; v++) {
                        for (h = 0; h < SENSOR_OTP_LSC_EEPROM_SIZE; h++) {
                                pdata.lsc_data[0].r[v][h] = r_matrix[v * SENSOR_OTP_LSC_EEPROM_SIZE + h];
                                pdata.lsc_data[0].gr[v][h] = gr_matrix[v * SENSOR_OTP_LSC_EEPROM_SIZE + h];
                                pdata.lsc_data[0].gb[v][h] = gb_matrix[v * SENSOR_OTP_LSC_EEPROM_SIZE + h];
                                pdata.lsc_data[0].b[v][h] = b_matrix[v * SENSOR_OTP_LSC_EEPROM_SIZE + h];
                        }
                }

                for (v = 0; v < SENSOR_OTP_LSC_H_GRID_NUM; v++) {
                        for (h = 0; h < SENSOR_OTP_LSC_H_GRID_NUM; h++) {
                                pdata.lsc_data[0].golden_r[v][h] = golden_r_matrix[v * 33 + h];
                                pdata.lsc_data[0].golden_gr[v][h] = golden_gr_matrix[v * 33 + h];
                                pdata.lsc_data[0].golden_gb[v][h] = golden_gb_matrix[v * 33 + h];
                                pdata.lsc_data[0].golden_b[v][h] = golden_b_matrix[v * 33 + h];
                        }
                }

                rett = ioctl(sensor_info->sen_devfd, SENSOR_OTP_PARAM, &pdata);
                if (rett < 0) {
                        vin_err("ioctl SENSOR_OTP_PARAM fail\n");
                }
                printf("sc202cs otp3-D65 enable\n");
        }
#endif

```


## AWB OTP

### 准备工作

#### Golden模组挑选

由模组厂按客户需求挑选

#### Golden模组ISP效果调试

在与客户确认的周期内完成Golden模组的ISP效果调试，参照ISP调试流程指导。

### 数据标定

#### 标定环境

Golden模组和Random模组的标定环境一致，可参照下表配置

|      名称       |                            参数                            |                            备注                            |
| :-------------: | :--------------------------------------------------------: | :--------------------------------------------------------: |
|    Gain设置     |           Digital   Gain： 1x；Analog Gain:  1x            |                             -                              |
| Mirror/Flip设置 |                    Mirror OFF; Flip OFF                    |                             -                              |
|     WB设置      |                            OFF                             |                             -                              |
|     PD设置      |                            OFF                             |                             -                              |
|       DPC       |                            OFF                             |                  拍图标定时不需要设置DPC                   |
|    Raw图格式    |                           Raw10                            |                             -                              |
|    图像尺寸     |                        常规尺寸均可                        |                      不支持尺寸为奇数                      |
|     G值要求     | 对于10bit RAW数据，G值推荐在扣除完BLC之后，在400-650左右。 |                             -                              |
|     G值分布     |              中心  （1/5 width * 1/5 Height）              |                  对于G值有要求的区域位置                   |
|  模组管控要求   |            扣除BLC, G值中心亮度/G值边缘亮度 < 5            | LSC支持最大16x Gain下发，但衰减过大易出现shading或块效应。 |
|    推荐色温     |                    3100K，4000K， 5800K                    |         radom与golden模组需在相同色温下拍摄raw数据         |


#### 标定流程

1. 建议使用灰卡标定，若使用积分球光源则保证模组镜头能通过窗口完全置于积分球内。
2. 参照3.1 标定环境章节表格要求设置模组，调节光源功率使成像中心区域扣除BLC之后的G值调整到400-650左右，拍摄RAW图。
3. 将拍摄的Raw图导入OTP tool，会计算获得R/GR/GB/B/rgRatio/bgRatio数据（数据范围取决于raw数据格式，建议按照16bit烧录）。对Random样件，将生成的数据写入sensor EEPROM；对Golden样件，将数据写入到sensor驱动中。数据生成示例请见5. 数据生成章节。
4. 以上步骤完成后，请图像调试工程师确认画面表现是否符合预期，若符合预期再进行批量烧录，完成OTP标定。


### OTP数据生成工具
awb otp工具为exe可执行文件（awb_otp.exe），计算需要的raw图配置参数和awb ratio参数以txt文件（otp_data.txt）解析的方式读入，otp数据的计算结果记录到txt文件（otp_result.txt）中。


#### 使用方法

1. 将需要计算的raw图命名为“otp.raw”，
2. 在“otp_data.txt”中配置相关参数，
3. 运行exe执行文件得到计算结果，保存在“otp_result.txt”文件中。

#### 参数说明

image_width：图像宽度
image_height：图像高度
pattern：图像bayer pattern，数值大小对应的格式为 0-RGGB， 1-GRBG， 2-GBRG， 3-BGGR
bls_r/bls_gr/bls_gb/bls_b：依次为r/gr/gb/b通道的bls数值，在统计图像时，这个值会被直接减去
awb_ratio：使用raw数据中央，尺寸为raw图宽和高1/awb_ratio的中心区域进行统计，其他区域不会被统计在内
std_rg_ratio_x：用于标定两条产线差异，std对应标准产线，该参数为x号模组的在这个产线上的色温标定结果（otp_result.txt）中的rg_ratio
std_bg_ratio_x：用于标定两条产线差异，std对应标准产线，该参数为x号模组的在这个产线上的色温标定结果（otp_result.txt）中的bg_ratio
ext_rg_ratio_x：用于标定两条产线差异，ext对应另一产线，该参数为x号模组的在这个产线上的色温标定结果（otp_result.txt）中的rg_ratio
ext_bg_ratio_x：用于标定两条产线差异，ext对应另一产线，该参数为x号模组的在这个产线上的色温标定结果（otp_result.txt）中的bg_ratio


**标定两条产线差异功能说明**

模组厂存在多条产线时，若不同产线之间标定所使用的色温存在偏差。比如对于A光，一个是3000K一个是2800K，这样就会导致同一个模组，在不同光源下烧录 otp 的时候烧录值会有些差异，最终导致AWB结果存在偏差。可以挑选5个随机模组，用于计算两条产线间的差异。

![ 色温偏差 ](./media/13-ct_correct.png)

标定步骤：
1. 挑选5个随机模组。
2. 在产线A的高中低三个色温下，拍摄获得raw数据，将std_rg_ratio_x等20个参数配置成1后，使用工具可以生成5个模组在三个色温下的rg_ratio和bg_ratio。
3. 在产线B的高中低三个色温下，拍摄同样的5个模组获得raw数据，将std_rg_ratio_x等20个参数配置成1后，使用工具可以生成5个模组在三个色温下的rg_ratio和bg_ratio。
4. 之后在对产线B的某一Random模组使用工具生成OTP参数时，可以将std_rg_ratio_x等20个参数配置对应色温的结果，这样工具会自动将两条产线的差异apply到OTP参数上。
例：在使用工具生成产线B的参数时，假设对应的色温为TL84。需要将std_rg_ratio_1、std_bg_ratio_1分别配置成产线A，TL84色温下第一个随机模组生成的数据rg_ratio和bg_ratio，std_rg_ratio_2、std_bg_ratio_2等依此类推。需要将ext_rg_ratio_1、ext_bg_ratio_1分别配置成产线B，TL84色温下第一个随机模组生成的数据rg_ratio和bg_ratio，ext_rg_ratio_2、ext_bg_ratio_2等依此类推。

注意：
如果是换成另一产线则需要按照同样的方法再次标定。如果不使用该功能，则需要将std_rg_ratio_x等20个参数全部配置成1。


### 生成数据结果

数据被存储于 otp_result.txt 文件内，其前部涵盖了计算使用的raw图配置数据等参数。
生成的各通道统计数据和ratio数据记录在 ”AWB OTP calculation result“字段下，即为对应色温下的AWB OTP相关数据。Random 模组生成的数据写入 EEPROM 中，而 Golden 模组生成的数据则在 sensor 驱动内记录。


### sensor驱动示例代码

在sensor初始化时刻，按照以下参考代码，调用对应的接口即可实现OTP功能的设置。

```c

{
        sensor_otp_t pdata = {0};
        pdata.otp_awb_enable = 1;
        pdata.awb_ct_num = 3;
        pdata.awb_golden_ct_num = 3;

        pdata.awb_data[0].color_temperature = COLOR_TEMPERATURE_3100K;
        pdata.awb_data[0].r = 36;
        pdata.awb_data[0].gr = 76;
        pdata.awb_data[0].gb = 76;
        pdata.awb_data[0].b = 49;
        pdata.awb_data[0].rg_ratio = 10;
        pdata.awb_data[0].bg_ratio = 10;

        pdata.awb_golden_data[0].color_temperature = COLOR_TEMPERATURE_3100K;
        pdata.awb_golden_data[0].r = 79;
        pdata.awb_golden_data[0].gr = 159;
        pdata.awb_golden_data[0].gb = 161;
        pdata.awb_golden_data[0].b = 105;
        pdata.awb_golden_data[0].rg_ratio = 2;
        pdata.awb_golden_data[0].bg_ratio = 2;

        pdata.awb_data[1].color_temperature = COLOR_TEMPERATURE_4000K;
        pdata.awb_data[1].r = 36;
        pdata.awb_data[1].gr = 76;
        pdata.awb_data[1].gb = 76;
        pdata.awb_data[1].b = 49;
        pdata.awb_data[1].rg_ratio = 10;
        pdata.awb_data[1].bg_ratio = 10;

        pdata.awb_golden_data[1].color_temperature = COLOR_TEMPERATURE_4000K;
        pdata.awb_golden_data[1].r = 79;
        pdata.awb_golden_data[1].gr = 159;
        pdata.awb_golden_data[1].gb = 161;
        pdata.awb_golden_data[1].b = 104;
        pdata.awb_golden_data[1].rg_ratio = 2;
        pdata.awb_golden_data[1].bg_ratio = 2;

        pdata.awb_data[2].color_temperature = COLOR_TEMPERATURE_5800K;
        pdata.awb_data[2].r = 35;
        pdata.awb_data[2].gr = 76;
        pdata.awb_data[2].gb = 76;
        pdata.awb_data[2].b = 49;
        pdata.awb_data[2].rg_ratio = 25;
        pdata.awb_data[2].bg_ratio = 25;

        pdata.awb_golden_data[2].color_temperature = COLOR_TEMPERATURE_5800K;
        pdata.awb_golden_data[2].r = 79;
        pdata.awb_golden_data[2].gr = 159;
        pdata.awb_golden_data[2].gb = 161;
        pdata.awb_golden_data[2].b = 105;
        pdata.awb_golden_data[2].rg_ratio = 23;
        pdata.awb_golden_data[2].bg_ratio = 23;
        printf("awb otp enable\n");
        hbn_camera_enable_otp(cam_fd, &pdata);  //cam_fd由hbn_camera_create创建
}

```
