/ components / micropython / port / src / omv / gc2145.c
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, &reg_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  }