gc2145.c
1 /** 2 * Copyright 2020 Sipeed Co.,Ltd. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdio.h> 18 19 #include "gc2145_regs.h" 20 #include "gc2145.h" 21 22 #include "dvp.h" 23 #include "plic.h" 24 #include "sleep.h" 25 #include "printf.h" 26 27 #include "sensor.h" 28 #include "cambus.h" 29 30 #include "mphalport.h" 31 32 int gc2145_reset(sensor_t *sensor) 33 { 34 uint16_t index = 0; 35 36 cambus_writeb(GC2145_ADDR, 0xFE, 0x01); 37 for (index = 0; sensor_gc2145_default_regs[index][0]; index++) 38 { 39 if (sensor_gc2145_default_regs[index][0] == 0xff) 40 { 41 mp_hal_delay_ms(sensor_gc2145_default_regs[index][1]); 42 continue; 43 } 44 // mp_printf(&mp_plat_print, "0x12,0x%02x,0x%02x,\r\n", sensor_gc2145_default_regs[index][0], sensor_gc2145_default_regs[index][1]);//debug 45 cambus_writeb(GC2145_ADDR, sensor_gc2145_default_regs[index][0], sensor_gc2145_default_regs[index][1]); 46 // mp_hal_delay_ms(1); 47 } 48 return 0; 49 } 50 51 static int gc2145_read_reg(sensor_t *sensor, uint8_t reg_addr) 52 { 53 uint8_t reg_data; 54 if (cambus_readb(sensor->slv_addr, reg_addr, ®_data) != 0) 55 { 56 return -1; 57 } 58 return reg_data; 59 } 60 61 static int gc2145_write_reg(sensor_t *sensor, uint8_t reg_addr, uint16_t reg_data) 62 { 63 return cambus_writeb(sensor->slv_addr, reg_addr, (uint8_t)reg_data); 64 } 65 66 static int gc2145_set_pixformat(sensor_t *sensor, pixformat_t pixformat) 67 { 68 // TODO: 69 return 0; 70 } 71 72 static int gc2145_set_framesize(sensor_t *sensor, framesize_t framesize) 73 { 74 int ret = 0; 75 uint16_t w = resolution[framesize][0]; 76 uint16_t h = resolution[framesize][1]; 77 78 int i = 0; 79 const uint8_t(*regs)[2]; 80 81 if (framesize == FRAMESIZE_QQVGA) 82 { 83 regs = sensor_gc2145_qqvga_config; 84 } 85 else if ((w <= 320) && (h <= 240)) 86 { 87 regs = sensor_gc2145_qvga_config; 88 } 89 else 90 { 91 regs = sensor_gc2145_vga_config; 92 } 93 94 while (regs[i][0]) 95 { 96 cambus_writeb(sensor->slv_addr, regs[i][0], regs[i][1]); 97 i++; 98 } 99 /* delay n ms */ 100 mp_hal_delay_ms(30); 101 dvp_set_image_size(w, h); 102 return ret; 103 } 104 105 static int gc2145_set_framerate(sensor_t *sensor, framerate_t framerate) 106 { 107 // TODO: 108 return 0; 109 } 110 111 #define NUM_CONTRAST_LEVELS (5) 112 static uint8_t contrast_regs[NUM_CONTRAST_LEVELS][2] = { 113 {0x80, 0x00}, 114 {0x80, 0x20}, 115 {0x80, 0x40}, 116 {0x80, 0x60}, 117 {0x80, 0x80}}; 118 119 static int gc2145_set_contrast(sensor_t *sensor, int level) 120 { 121 int ret = 0; 122 123 level += (NUM_CONTRAST_LEVELS / 2); 124 if (level < 0 || level > NUM_CONTRAST_LEVELS) 125 { 126 return -1; 127 } 128 cambus_writeb(sensor->slv_addr, 0xfe, 0x00); 129 cambus_writeb(sensor->slv_addr, 0xd4, contrast_regs[level][0]); 130 cambus_writeb(sensor->slv_addr, 0xd3, contrast_regs[level][1]); 131 return ret; 132 } 133 134 static int gc2145_set_brightness(sensor_t *sensor, int level) 135 { 136 int ret = 0; 137 // TODO: 138 return ret; 139 } 140 141 #define NUM_SATURATION_LEVELS (5) 142 static uint8_t saturation_regs[NUM_SATURATION_LEVELS][3] = { 143 {0x00, 0x00, 0x00}, 144 {0x10, 0x10, 0x10}, 145 {0x20, 0x20, 0x20}, 146 {0x30, 0x30, 0x30}, 147 {0x40, 0x40, 0x40}, 148 }; 149 static int gc2145_set_saturation(sensor_t *sensor, int level) 150 { 151 int ret = 0; 152 level += (NUM_CONTRAST_LEVELS / 2); 153 if (level < 0 || level > NUM_CONTRAST_LEVELS) 154 { 155 return -1; 156 } 157 cambus_writeb(sensor->slv_addr, 0xfe, 0x00); 158 cambus_writeb(sensor->slv_addr, 0xd0, saturation_regs[level][0]); 159 cambus_writeb(sensor->slv_addr, 0xd1, saturation_regs[level][1]); 160 cambus_writeb(sensor->slv_addr, 0xd2, saturation_regs[level][2]); 161 return ret; 162 } 163 164 static int gc2145_set_gainceiling(sensor_t *sensor, gainceiling_t gainceiling) 165 { 166 int ret = 0; 167 // TODO: 168 return ret; 169 } 170 171 static int gc2145_set_quality(sensor_t *sensor, int qs) 172 { 173 int ret = 0; 174 // TODO: 175 return ret; 176 } 177 178 static int gc2145_set_colorbar(sensor_t *sensor, int enable) 179 { 180 int ret = 0; 181 // TODO: 182 return ret; 183 } 184 185 static int gc2145_set_auto_gain(sensor_t *sensor, int enable, float gain_db, float gain_db_ceiling) 186 { 187 int ret = 0; 188 // TODO: 189 return ret; 190 } 191 192 static int gc2145_get_gain_db(sensor_t *sensor, float *gain_db) 193 { 194 int ret = 0; 195 // TODO: 196 return ret; 197 } 198 199 static int gc2145_set_auto_exposure(sensor_t *sensor, int enable, int exposure_us) 200 { 201 int ret = 0; 202 uint8_t temp; 203 cambus_writeb(sensor->slv_addr, 0xfe, 0x00); 204 cambus_readb(sensor->slv_addr, 0x4f, &temp); 205 if (enable != 0) 206 { 207 cambus_writeb(sensor->slv_addr, 0x4f, temp | 0x01); // enable 208 if (exposure_us != -1) 209 { 210 cambus_writeb(sensor->slv_addr, 0xfe, 0x01); 211 cambus_writeb(sensor->slv_addr, 0x2b, (uint8_t)(((uint16_t)exposure_us) >> 8)); 212 cambus_writeb(sensor->slv_addr, 0x2c, (uint8_t)(((uint16_t)exposure_us))); 213 } 214 } 215 else 216 { 217 cambus_writeb(sensor->slv_addr, 0x4f, temp & 0xfe); // disable 218 if (exposure_us != -1) 219 { 220 cambus_writeb(sensor->slv_addr, 0xfe, 0x01); 221 cambus_writeb(sensor->slv_addr, 0x2b, (uint8_t)(((uint16_t)exposure_us) >> 8)); 222 cambus_writeb(sensor->slv_addr, 0x2c, (uint8_t)(((uint16_t)exposure_us))); 223 } 224 } 225 return ret; 226 } 227 228 static int gc2145_get_exposure_us(sensor_t *sensor, int *exposure_us) 229 { 230 int ret = 0; 231 // TODO: 232 return ret; 233 } 234 235 static int gc2145_set_auto_whitebal(sensor_t *sensor, int enable, float r_gain_db, float g_gain_db, float b_gain_db) 236 { 237 int ret = 0; 238 uint8_t temp; 239 cambus_writeb(sensor->slv_addr, 0xfe, 0x00); 240 cambus_readb(sensor->slv_addr, 0x42, &temp); 241 if (enable != 0) 242 { 243 cambus_writeb(sensor->slv_addr, 0x42, temp | 0x02); // enable 244 if (!isnanf(r_gain_db)) 245 cambus_writeb(sensor->slv_addr, 0x80, (uint8_t)r_gain_db); //limit 246 if (!isnanf(g_gain_db)) 247 cambus_writeb(sensor->slv_addr, 0x81, (uint8_t)g_gain_db); 248 if (!isnanf(b_gain_db)) 249 cambus_writeb(sensor->slv_addr, 0x82, (uint8_t)b_gain_db); 250 } 251 else 252 { 253 cambus_writeb(sensor->slv_addr, 0x42, temp & 0xfd); // disable 254 if (!isnanf(r_gain_db)) 255 cambus_writeb(sensor->slv_addr, 0x77, (uint8_t)r_gain_db); 256 if (!isnanf(g_gain_db)) 257 cambus_writeb(sensor->slv_addr, 0x78, (uint8_t)g_gain_db); 258 if (!isnanf(b_gain_db)) 259 cambus_writeb(sensor->slv_addr, 0x79, (uint8_t)b_gain_db); 260 } 261 return ret; 262 } 263 264 static int gc2145_get_rgb_gain_db(sensor_t *sensor, float *r_gain_db, float *g_gain_db, float *b_gain_db) 265 { 266 int ret = 0; 267 // TODO: 268 return ret; 269 } 270 271 static int gc2145_set_hmirror(sensor_t *sensor, int enable) 272 { 273 uint8_t data; 274 cambus_readb(GC2145_ADDR, 0x17, &data); 275 data = data & 0xFC; 276 if (enable) 277 { 278 data = data | 0x01 | (sensor->vflip ? 0x02 : 0x00); 279 } 280 else 281 { 282 data = data | (sensor->vflip ? 0x02 : 0x00); 283 } 284 return cambus_writeb(GC2145_ADDR, 0x17, data); 285 } 286 287 static int gc2145_set_vflip(sensor_t *sensor, int enable) 288 { 289 uint8_t data; 290 cambus_readb(GC2145_ADDR, 0x17, &data); 291 data = data & 0xFC; 292 if (enable) 293 { 294 data = data | 0x02 | (sensor->hmirror ? 0x01 : 0x00); 295 } 296 else 297 { 298 data = data | (sensor->hmirror ? 0x01 : 0x00); 299 } 300 return cambus_writeb(GC2145_ADDR, 0x17, data); 301 } 302 303 int gc2145_init(sensor_t *sensor) 304 { 305 //Initialize sensor structure. 306 sensor->gs_bpp = 2; 307 sensor->reset = gc2145_reset; 308 sensor->read_reg = gc2145_read_reg; 309 sensor->write_reg = gc2145_write_reg; 310 sensor->set_pixformat = gc2145_set_pixformat; 311 sensor->set_framesize = gc2145_set_framesize; 312 sensor->set_framerate = gc2145_set_framerate; 313 sensor->set_contrast = gc2145_set_contrast; 314 sensor->set_brightness = gc2145_set_brightness; 315 sensor->set_saturation = gc2145_set_saturation; 316 sensor->set_gainceiling = gc2145_set_gainceiling; 317 sensor->set_quality = gc2145_set_quality; 318 sensor->set_colorbar = gc2145_set_colorbar; 319 sensor->set_auto_gain = gc2145_set_auto_gain; 320 sensor->get_gain_db = gc2145_get_gain_db; 321 sensor->set_auto_exposure = gc2145_set_auto_exposure; 322 sensor->get_exposure_us = gc2145_get_exposure_us; 323 sensor->set_auto_whitebal = gc2145_set_auto_whitebal; 324 sensor->get_rgb_gain_db = gc2145_get_rgb_gain_db; 325 sensor->set_hmirror = gc2145_set_hmirror; 326 sensor->set_vflip = gc2145_set_vflip; 327 328 // Set sensor flags 329 SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_VSYNC, 0); 330 SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_HSYNC, 0); 331 SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_PIXCK, 1); 332 SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_FSYNC, 0); 333 SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_JPEGE, 1); 334 335 return 0; 336 }