Commit 3437e6f6 authored by Oleg Dzhimiev's avatar Oleg Dzhimiev

mt9f002: vertical and horizontal flips (mirroring)

parent 73cd475f
...@@ -760,6 +760,26 @@ int mt9f002_calc_frame_length_lines(int y_addr_start, ...@@ -760,6 +760,26 @@ int mt9f002_calc_frame_length_lines(int y_addr_start,
return v0; return v0;
} }
// also defines vertical blanking
int mt9f002_calc_frame_length_lines_2(int height,
int min_frame_blanking_lines){
int v0;
int subsampling_factor = 1;
v0 = height/subsampling_factor + min_frame_blanking_lines;
/*
if (coarse_exposure>(v0-1)){
v0 = coarse_exposure + 1;
pr_info("frame_length_lines will get extended\n");
}
*/
return v0;
}
// also defines horizontal blanking // also defines horizontal blanking
int mt9f002_calc_line_length_pck(int x_addr_start, int mt9f002_calc_line_length_pck(int x_addr_start,
int x_addr_end, int x_addr_end,
...@@ -845,8 +865,13 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port ...@@ -845,8 +865,13 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port
//int min_line_length_pck = 0x04c8; //int min_line_length_pck = 0x04c8;
int ww_odd_inc = 1; int ww_odd_inc = 1;
// fll - frame length lines
// llp - line length pck
int fll, llp; int fll, llp;
int whs_vact_delay = 0;
int whe_vact_delay = 0;
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16); dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
if (frame16 >= PARS_FRAMES) return -1; // wrong frame if (frame16 >= PARS_FRAMES) return -1; // wrong frame
...@@ -867,10 +892,10 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port ...@@ -867,10 +892,10 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port
compressor_margin = (thispars->pars[P_SENSOR_PIXH] - thispars->pars[P_WOI_WIDTH]) >> 1; compressor_margin = (thispars->pars[P_SENSOR_PIXH] - thispars->pars[P_WOI_WIDTH]) >> 1;
//pr_info("Compressor margin = %d\n",compressor_margin); //pr_info("Compressor margin = %d\n",compressor_margin);
// 10338 is _not_ flipped (as the other boards, but for legacy compatibility....)
flip=((thispars->pars[P_FLIPH] & 1) | ((thispars->pars[P_FLIPV] & 1) << 1 )) ^ sensor->init_flips; flip=((thispars->pars[P_FLIPH] & 1) | ((thispars->pars[P_FLIPV] & 1) << 1 )) ^ sensor->init_flips;
flipX = flip & 1; flipX = flip & 1;
flipY = (flip & 2)? 1:0; flipY = (flip & 2)? 1:0;
d = 2 * bh * (ww / (2 * bh)); d = 2 * bh * (ww / (2 * bh));
// correct window width if needed // correct window width if needed
...@@ -901,21 +926,24 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port ...@@ -901,21 +926,24 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port
// get back to this // get back to this
if (!thispars->pars[P_OVERSIZE]) { if (!thispars->pars[P_OVERSIZE]) {
if(flipX) { //if(flipX) {
//pr_info("{%d} flipX = %d\n",sensor_port, flipX); //wl = sensor->clearWidth - ww - wl - (2 * COLOR_MARGINS) * dh;
wl = sensor->clearWidth - ww - wl - (2 * COLOR_MARGINS) * dh; //if (wl < 0) wl = 0;
if(wl < 0) wl = 0; //}
} //if(flipY) {
if(flipY) { // wt = sensor->clearHeight - wh - wt - (2 * COLOR_MARGINS) * dv;
//pr_info("{%d} flipY = %d\n",sensor_port, flipY); // if (wt < 0) wt = 0;
wt = sensor->clearHeight - wh - wt - (2 * COLOR_MARGINS) * dv; //}
if(wt < 0) wt = 0;
}
// apply clearTop/clearLeft // apply clearTop/clearLeft
wt = (wt + sensor->clearTop) & 0xfffe; wt = (wt + sensor->clearTop) & 0xfffe;
wl = (wl + sensor->clearLeft) & 0xfffe; wl = (wl + sensor->clearLeft) & 0xfffe;
dev_dbg(g_dev_ptr,"{%d} wl =0x%x, wt=0x%x\n",sensor_port, wl, wt); dev_dbg(g_dev_ptr,"{%d} wl =0x%x, wt=0x%x\n",sensor_port, wl, wt);
//pr_info("{%d} wl =0x%x, wt=0x%x\n",sensor_port, wl, wt);
// apply VACT_DELAY
whs_vact_delay = MT9F002_VACT_DELAY*(flipX?0:1);
whe_vact_delay = MT9F002_VACT_DELAY*(dv+(flipX?1:0));
/* /*
// apply binning restrictions // apply binning restrictions
...@@ -928,15 +956,18 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port ...@@ -928,15 +956,18 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port
i += d; i += d;
wl = i; wl = i;
*/ */
// if P_OVERSIZE
}else{
whe_vact_delay = MT9F002_VACT_DELAY*(dv+1);
} }
wws = wl; wws = wl;
wwe = wws + ww - 1; wwe = wws + ww - 1;
// need sensor->clearTop-MT9F002_VACT_DELAY - beacause the 1st 2 rows are ignored // need sensor->clearTop-MT9F002_VACT_DELAY - beacause the 1st 2 rows are ignored
whs = wt - MT9F002_VACT_DELAY; whs = wt - whs_vact_delay;
//whe = whs + wh + MT9F002_VACT_DELAY*(dv+1) - 1; // ?! //whe = whs + wh + MT9F002_VACT_DELAY*(dv+1) - 1; // ?!
whe = whs + wh + MT9F002_VACT_DELAY*(dv) - 1; whe = whs + wh + whe_vact_delay - 1;
// will be different if binning/skipping // will be different if binning/skipping
wh = whe - whs + 1; wh = whe - whs + 1;
...@@ -974,7 +1005,8 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port ...@@ -974,7 +1005,8 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port
sensor_port, sensor_port, frame16, (int) P_MT9F002_Y_OUTPUT_SIZE, (int) wh); sensor_port, sensor_port, frame16, (int) P_MT9F002_Y_OUTPUT_SIZE, (int) wh);
} }
// recalc something after this one? /*
// this is NOT needed when woi sizes change
//fll = mt9f002_calc_frame_length_lines(thispars); //fll = mt9f002_calc_frame_length_lines(thispars);
fll = mt9f002_calc_frame_length_lines(whs,whe,min_frame_blanking_lines); fll = mt9f002_calc_frame_length_lines(whs,whe,min_frame_blanking_lines);
// this sets the vertical blanking // this sets the vertical blanking
...@@ -983,6 +1015,7 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port ...@@ -983,6 +1015,7 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port
(int) thispars->pars[P_SENSOR_REGS+P_MT9F002_FRAME_LENGTH_LINES], fll); (int) thispars->pars[P_SENSOR_REGS+P_MT9F002_FRAME_LENGTH_LINES], fll);
SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_MT9F002_FRAME_LENGTH_LINES, fll); SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_MT9F002_FRAME_LENGTH_LINES, fll);
} }
*/
// need this fix for max possible fps // need this fix for max possible fps
if (ww >= X_OUTPUT_BORDER_SIZE){ if (ww >= X_OUTPUT_BORDER_SIZE){
...@@ -1001,6 +1034,13 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port ...@@ -1001,6 +1034,13 @@ int mt9f002_pgm_window_common (int sensor_port, ///< sensor port
// write flips and skips // write flips and skips
// reg 0x3040 = P_REG_MT9F002_READ_MODE // reg 0x3040 = P_REG_MT9F002_READ_MODE
v = (thispars->pars[P_SENSOR_REGS+P_MT9F002_READ_MODE] & 0x3fff) | // preserve other bits from shadows
(flipX ? (1 << 14) : 0) | // FLIPH - will control just alternative rows
(flipY ? (1 << 15) : 0) ; // FLIPV
if (v != thispars->pars[P_SENSOR_REGS+P_MT9F002_READ_MODE]) {
SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_MT9F002_READ_MODE, v);
}
//P_MT9F002_READ_MODE //P_MT9F002_READ_MODE
// bits // bits
...@@ -1100,12 +1140,12 @@ int compare_to_trig_period_mt9f002(int sensor_port, ///< sensor po ...@@ -1100,12 +1140,12 @@ int compare_to_trig_period_mt9f002(int sensor_port, ///< sensor po
} }
/** Check if compressor can keep up, limit sensor FPS if needed /** Check if compressor can keep up, limit sensor FPS if needed
* FPS is limited by increasing verical blanking, it can not be be made too big, so this method does not work to make time lapse rate. horisontal blanking * FPS is limited by increasing vertical blanking, it can not be be made too big, so this method does not work to make time lapse rate.
* is kept at minimum (to reduce ERS effect) if not specified. If it is specified (>minimal) - it will be used instead. * Horizontal blanking is kept at minimum (to reduce ERS effect) if not specified. If it is specified (>minimal) - it will be used instead.
* calculate line period. * Calculate line period.
* *
* FIXME - uses P_VIRTUAL_WIDTH w/o decreasing it when changing image size? Replace VIRT_WIDTH with HOR_BANK? * FIXME - uses P_VIRTUAL_WIDTH w/o decreasing it when changing image size? Replace VIRT_WIDTH with HOR_BANK?
* Or require always set them to zero when chnaging WOI? * Or require always set them to zero when changing WOI?
* FIXME for multisensor - needs per-sensor individual parameters. This uses sensor registers, not the general parameters (i.e. height) */ * FIXME for multisensor - needs per-sensor individual parameters. This uses sensor registers, not the general parameters (i.e. height) */
int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port number (0..3) int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port number (0..3)
struct sensor_t * sensor, ///< sensor static parameters (capabilities) struct sensor_t * sensor, ///< sensor static parameters (capabilities)
...@@ -1120,13 +1160,15 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb ...@@ -1120,13 +1160,15 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb
int nupdate=0; int nupdate=0;
// decimation horizontal // decimation horizontal
int dh= thispars->pars[P_DCM_HOR]?thispars->pars[P_DCM_HOR]:1; int dh = thispars->pars[P_DCM_HOR]?thispars->pars[P_DCM_HOR]:1;
int dv = thispars->pars[P_DCM_VERT]?thispars->pars[P_DCM_VERT]:1;
// width = PIXELS HORIZONTAL // width = PIXELS HORIZONTAL
int ww= thispars->pars[P_SENSOR_PIXH] * dh; int ww = thispars->pars[P_SENSOR_PIXH] * dh;
int wh = thispars->pars[P_SENSOR_PIXV] * dv;
int binning_cost = 0; int binning_cost = 0;
int width,i; int width,i;
int row_time_in_pixels=0; int row_time_in_pixels = 0;
int hor_blank_min; int hor_blank_min;
int hor_blank=0; int hor_blank=0;
int p1, p2, pix_period, sclk,fp1000s; int p1, p2, pix_period, sclk,fp1000s;
...@@ -1134,8 +1176,10 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb ...@@ -1134,8 +1176,10 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb
int height; int height;
// virtual height read from sensor register // virtual height read from sensor register
int virt_height; int virt_height;
// minimum allowed by sensor for given wxh
int virt_height_min;
// virtual height calculated from trig_period // virtual height calculated from trig_period
int virt_height_trig; int virt_height_trig = 0;
int vert_blank; int vert_blank;
uint64_t ull_fp1000s; uint64_t ull_fp1000s;
...@@ -1236,14 +1280,16 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb ...@@ -1236,14 +1280,16 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb
if((height * dv) < wh) height++; if((height * dv) < wh) height++;
*/ */
height = thispars->pars[P_SENSOR_PIXV];
// this should be based on exposure // this should be based on exposure
//virt_height = height + sensor->minVertBlank; //virt_height = height + sensor->minVertBlank;
//virt_height = mt9f002_calc_frame_length_lines(thispars); //virt_height = mt9f002_calc_frame_length_lines(thispars);
// this is allowed minimum // this is allowed minimum
virt_height_min = mt9f002_calc_frame_length_lines_2(wh,thispars->pars[P_SENSOR_REGS+P_MT9F002_MIN_FRAME_BLANKING_LINES]);
// this is current setting
virt_height = thispars->pars[P_SENSOR_REGS+P_MT9F002_FRAME_LENGTH_LINES]; virt_height = thispars->pars[P_SENSOR_REGS+P_MT9F002_FRAME_LENGTH_LINES];
// override if really needed
if (thispars->pars[P_VIRT_KEEP]) { if (thispars->pars[P_VIRT_KEEP]) {
if (virt_height < thispars->pars[P_VIRT_HEIGHT]) { if (virt_height < thispars->pars[P_VIRT_HEIGHT]) {
virt_height = thispars->pars[P_VIRT_HEIGHT]; virt_height = thispars->pars[P_VIRT_HEIGHT];
...@@ -1252,6 +1298,8 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb ...@@ -1252,6 +1298,8 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb
dev_dbg(g_dev_ptr,"{%d} height =%d(0x%x), virt_height=%d(0x%x)\n",sensor_port,height,height,virt_height,virt_height); dev_dbg(g_dev_ptr,"{%d} height =%d(0x%x), virt_height=%d(0x%x)\n",sensor_port,height,height,virt_height,virt_height);
// this is related to the case when TRIG_PERIOD is 'jumping' back and forth initialization bug
if (thispars->pars[P_TRIG_PERIOD]>=256){
// trig_period can be long, but it is already compared to P_PERIOD_MIN (compressor capability) // trig_period can be long, but it is already compared to P_PERIOD_MIN (compressor capability)
trig_period = camsync_to_sensor(thispars->pars[P_TRIG_PERIOD], thispars->pars[P_CLK_SENSOR]); trig_period = camsync_to_sensor(thispars->pars[P_TRIG_PERIOD], thispars->pars[P_CLK_SENSOR]);
...@@ -1266,6 +1314,10 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb ...@@ -1266,6 +1314,10 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb
virt_height_trig = 0xffff; virt_height_trig = 0xffff;
} }
// compare against minimum
if (virt_height_trig < virt_height_min) virt_height_trig = virt_height_min;
}
// round up? no // round up? no
//if ((row_time_in_pixels * virt_height_min) < trig_period) virt_height_min++; //if ((row_time_in_pixels * virt_height_min) < trig_period) virt_height_min++;
...@@ -1273,7 +1325,10 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb ...@@ -1273,7 +1325,10 @@ int mt9f002_pgm_limitfps (int sensor_port, ///< sensor port numb
//if (virt_height < virt_height_min) virt_height = virt_height_min; //if (virt_height < virt_height_min) virt_height = virt_height_min;
// update except if zero // update except if zero
if (virt_height_trig) virt_height = virt_height_trig;
if (virt_height_trig) {
virt_height = virt_height_trig;
}
dev_dbg(g_dev_ptr,"{%d} height =%d(0x%x), modified virt_height=%d(0x%x)\n",sensor_port,height,height,virt_height,virt_height); dev_dbg(g_dev_ptr,"{%d} height =%d(0x%x), modified virt_height=%d(0x%x)\n",sensor_port,height,height,virt_height,virt_height);
...@@ -1500,58 +1555,6 @@ int mt9f002_pgm_exposure (int sensor_port, ///< sensor port number ...@@ -1500,58 +1555,6 @@ int mt9f002_pgm_exposure (int sensor_port, ///< sensor port number
} }
/* /*
dev_dbg(g_dev_ptr,"{%d} sensor_port=%d, frame16=%d, frame=0x%lx (%s)exposure=0x%lx, (%s)video_exposure=0x%lx\n",sensor_port, sensor_port, frame16, thispars->pars[P_FRAME], FRAMEPAR_MODIFIED(P_EXPOS)?"*":" ",thispars->pars[P_EXPOS],FRAMEPAR_MODIFIED(P_VEXPOS)?"*":" ",thispars->pars[P_VEXPOS] );
dev_dbg(g_dev_ptr,"{%d} row_time_in_pixels=0x%x\n",sensor_port, row_time_in_pixels); // 0
//vert_blank= thispars->pars[P_SENSOR_REGS+P_MT9X001_VERTBLANK ];
vert_blank=0;
dev_dbg(g_dev_ptr,"{%d} vert_blank=0x%x\n",sensor_port,vert_blank); // 0
// if video exposure is non-zero, P_VEXPOS is marked as modified or P_EXPOS is not modified - use video exposure (lines), else - absolute exposure (usec)
if ((FRAMEPAR_MODIFIED(P_VEXPOS) || ! (FRAMEPAR_MODIFIED(P_EXPOS) || FRAMEPAR_MODIFIED(P_VIRT_WIDTH)) )) { // use number of lines
dev_dbg(g_dev_ptr,"{%d} exposure=%d (0x%x), video_exposure=%d (0x%x)\n",sensor_port, (int) thispars->pars[P_VEXPOS], (int) thispars->pars[P_VEXPOS], (int) video_exposure, (int) video_exposure);
#if USELONGLONG
ull_exposure= ((long long)(video_exposure * row_time_in_pixels)) * ((long long) 1000000);
#ifdef __div64_32
__div64_32(&ull_exposure, sclk);
#else
do_div(ull_exposure, sclk);
// ull_exposure /= sclk;
#endif
exposure= ull_exposure;
#else
exposure = (100*video_exposure * row_time_in_pixels) / (sclk/10000); // in microseconds
#endif
use_vexp=1;
} else { // use time in microseconds
exposure = thispars->pars[P_EXPOS];
#if USELONGLONG
ull_video_exposure= (long long) exposure * (long long) sclk;
#ifdef __div64_32
__div64_32(&ull_video_exposure, row_time_in_pixels);
__div64_32(&ull_video_exposure, 1000000);
#else
do_div(ull_video_exposure, row_time_in_pixels);
do_div(ull_video_exposure, 1000000);
// ull_video_exposure /= row_time_in_pixels;
// ull_video_exposure /= 1000000;
#endif
video_exposure= ull_video_exposure;
#else
///TODO - use shifts, not division where possible?
if (exposure<10000) { // <0.01 sec
video_exposure = ( exposure * (sclk/1000))/ (row_time_in_pixels*1000);
} else if (exposure<100000) { // 0.1 sec
video_exposure = ( (exposure/10) * (sclk/1000))/ (row_time_in_pixels * 100);
} else if (exposure<1000000) { // 1.0 sec
video_exposure = ( (exposure/100) * (sclk/1000))/ (row_time_in_pixels * 10);
} else {
video_exposure = ( (exposure/1000) * (sclk/1000))/ (row_time_in_pixels );
}
#endif
}
if (exposure <1) exposure=1;
if (video_exposure <1) video_exposure=1;
// is video exposure longer than maximal for the sensor? // is video exposure longer than maximal for the sensor?
if (video_exposure > sensor->maxShutter) { if (video_exposure > sensor->maxShutter) {
...@@ -1641,12 +1644,14 @@ int mt9f002_pgm_exposure (int sensor_port, ///< sensor port number ...@@ -1641,12 +1644,14 @@ int mt9f002_pgm_exposure (int sensor_port, ///< sensor port number
} }
*/ */
/*
// update // update
if (virt_height != thispars->pars[P_SENSOR_REGS+P_MT9F002_FRAME_LENGTH_LINES]){ if (virt_height != thispars->pars[P_SENSOR_REGS+P_MT9F002_FRAME_LENGTH_LINES]){
//pr_info("LIMIT_FPS, old frame_length_lines=0x%08x, new frame_length_lines=0x%08x\n", //pr_info("LIMIT_FPS, old frame_length_lines=0x%08x, new frame_length_lines=0x%08x\n",
// thispars->pars[P_SENSOR_REGS+P_MT9F002_FRAME_LENGTH_LINES],virt_height); // thispars->pars[P_SENSOR_REGS+P_MT9F002_FRAME_LENGTH_LINES],virt_height);
SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_MT9F002_FRAME_LENGTH_LINES, virt_height); SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_MT9F002_FRAME_LENGTH_LINES, virt_height);
} }
*/
// coarse integration time // coarse integration time
if (coarse_exposure != thispars->pars[P_SENSOR_REGS+P_MT9F002_COARSE_INTEGRATION_TIME]) { if (coarse_exposure != thispars->pars[P_SENSOR_REGS+P_MT9F002_COARSE_INTEGRATION_TIME]) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment